update eclipse.org-common

Signed-off-by: Christopher Guindon <chris.guindon@eclipse-foundation.org>
diff --git a/eclipse.org-common/classes/ads/ad.class.php b/eclipse.org-common/classes/ads/ad.class.php
index 08f2e4b..b78b758 100644
--- a/eclipse.org-common/classes/ads/ad.class.php
+++ b/eclipse.org-common/classes/ads/ad.class.php
@@ -1,15 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2015, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *    Eric Poirier (Eclipse Foundation)
- *******************************************************************************/
+ *   Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 require_once("campaignImpression.class.php");
 
diff --git a/eclipse.org-common/classes/ads/adReports.class.php b/eclipse.org-common/classes/ads/adReports.class.php
index dc7de26..e440c5f 100644
--- a/eclipse.org-common/classes/ads/adReports.class.php
+++ b/eclipse.org-common/classes/ads/adReports.class.php
@@ -1,14 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright(c) 2015-2020 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2015, 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier(Eclipse Foundation)
- *******************************************************************************/
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 require_once(realpath(dirname(__FILE__) . "/../../system/app.class.php"));
 require_once(realpath(dirname(__FILE__) . "/../../system/session.class.php"));
@@ -86,7 +89,7 @@
    * This function creates a new temporary impressions table
    * */
   private function _fetchImpressions() {
-    $sql = "SELECT /* adReports.class.php:89 */
+    $sql = "SELECT /* eclipse.org-common:classes/ads/adReports.class.php:92 */
             campaignKey,
             count(*) as impressions,
             str_to_date(concat(yearweek(TimeImpressed), ' Sunday'), '%X%V %W') as date
@@ -109,7 +112,7 @@
    * This function creates a new temporary Clicks table
    * */
   private function _fetchClicks() {
-    $sql = "SELECT /* adReports.class.php:112 */
+    $sql = "SELECT /* eclipse.org-common:classes/ads/adReports.class.php:115 */
               campaignKey,
               count(*) as clicks,
               str_to_date(concat(yearweek(TimeClicked), ' Sunday'), '%X%V %W') as date
diff --git a/eclipse.org-common/classes/ads/campaign.class.php b/eclipse.org-common/classes/ads/campaign.class.php
index 9435e33..2affb4b 100644
--- a/eclipse.org-common/classes/ads/campaign.class.php
+++ b/eclipse.org-common/classes/ads/campaign.class.php
@@ -1,14 +1,18 @@
 <?php
-/*******************************************************************************
- * Copyright(c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2015, 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier(Eclipse Foundation)
- *******************************************************************************/
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
 require_once(realpath(dirname(__FILE__) . "/../../system/app.class.php"));
 require_once(realpath(dirname(__FILE__) . "/../../system/session.class.php"));
 
diff --git a/eclipse.org-common/classes/ads/campaignImpression.class.php b/eclipse.org-common/classes/ads/campaignImpression.class.php
index 0a72ea2..91305b5 100644
--- a/eclipse.org-common/classes/ads/campaignImpression.class.php
+++ b/eclipse.org-common/classes/ads/campaignImpression.class.php
@@ -1,15 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2010, 2014, 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2010, 2014, 2015, 2018 Eclipse Foundation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
  *    Nathan Gervais (Eclipse Foundation) - Initial API + Implementation
- *    Christopher Guindon (Eclipse Foundation)
- *******************************************************************************/
+ *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 require_once(realpath(dirname(__FILE__) . "/../../system/app.class.php"));
 
@@ -26,38 +28,16 @@
    * The Eclipse campaign key
    * @var unknown
    */
-  private $campaign_key = 0;
-
-  /**
-   * The description of the page that will display the ad
-   * @var string
-   */
-  private $source = '';
-
-  /**
-   * The remote address of the user that will view the ad
-   * @var string
-   */
-  private $remote_addr = '';
-
-  /**
-   * The current UNIX timestamp
-   * @var string
-   */
-  private $timestamp = '';
+  private $campaign_key = '';
 
   /**
    * Constructor
    *
    * @param string $_campaign_key
-   * @param string $_source
-   * @param string $_remote_addr
+   * @param string $_source (deprecated)
    */
-  function __construct($_campaign_key, $_source, $_remote_addr) {
+  function __construct($_campaign_key, $_source = NULL) {
     $this->campaign_key = $_campaign_key;
-    $this->source = $_source;
-    $this->remote_addr = $_remote_addr;
-    $this->timestamp = date('Y-m-d H:i:s');
   }
 
   /**
@@ -67,7 +47,9 @@
     $App = new App();
 
     // We dont register ad impressions in devmode
-    if ($App->devmode == TRUE) return;
+    if ($App->devmode == TRUE) {
+      return FALSE;
+    }
 
     if (rand(0, 1000) < 1) {
       // 1 of every 1,000 hits (0.1%) will clean up
@@ -75,15 +57,25 @@
       $App->eclipse_sql($deleteSql);
     }
 
+    $url = parse_url($_SERVER['SCRIPT_URI']);
+    $host = (!empty($url['host'])) ? $App->returnQuotedString($App->sqlSanitize(preg_replace('#^www\.(.+\.)#i', '$1', $url['host']))) : 'NULL';
+    $source = (!empty($url['path'])) ? $App->returnQuotedString($App->sqlSanitize($url['path'])) : 'NULL';
+
+    $ImpressionClickID = $App->getAlphaCode(rand(32, 64));
+    $ip =  $App->anonymizeIP($App->getRemoteIPAddress());
+    $ip = (!empty($ip)) ? $App->returnQuotedString($App->sqlSanitize($ip)) : 'NULL';
+
     $sql = "INSERT DELAYED INTO CampaignImpressions
-        (CampaignKey, Source, HostName, TimeImpressed)
+        (ImpressionClickID, CampaignKey, Source, HostName, TimeImpressed, Host)
         VALUES (
+      " . $App->returnQuotedString($App->sqlSanitize($ImpressionClickID)) . ",
       " . $App->returnQuotedString($App->sqlSanitize($this->campaign_key)) . ",
-      " . $App->returnQuotedString($App->sqlSanitize($this->source)) . ",
-      " . $App->returnQuotedString($App->sqlSanitize($this->remote_addr)) . ",
-      " . $App->returnQuotedString($App->sqlSanitize($this->timestamp)) . ")";
+      " . $source . ",
+      " . $ip . ",
+      now(),
+      " . $host . ")";
 
     $result = $App->eclipse_sql($sql);
-    return TRUE;
+    return $ImpressionClickID;
   }
 }
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/campaignManager.class.php b/eclipse.org-common/classes/ads/campaignManager.class.php
index 5b3695a..6dde2af 100644
--- a/eclipse.org-common/classes/ads/campaignManager.class.php
+++ b/eclipse.org-common/classes/ads/campaignManager.class.php
@@ -1,14 +1,18 @@
 <?php
-/*******************************************************************************
- * Copyright(c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2015, 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier(Eclipse Foundation)
- *******************************************************************************/
+ *   Eric Poirier (Eclipse Foundation) - Initial implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
 require_once("campaign.class.php");
 class CampaignManager extends Campaign{
 
diff --git a/eclipse.org-common/classes/ads/downloadsBannerAd.class.php b/eclipse.org-common/classes/ads/downloadsBannerAd.class.php
index 1979360..b7a20fe 100644
--- a/eclipse.org-common/classes/ads/downloadsBannerAd.class.php
+++ b/eclipse.org-common/classes/ads/downloadsBannerAd.class.php
@@ -18,34 +18,22 @@
 
   public function __construct() {
     parent::__construct();
+    if (time() < strtotime("23 October 2018")) {
+      $campaign = "PROMO_ECE2018_DOWNLOADS_PAGE";
+      $content['body'] = "Register now for EclipseCon Europe 2018 ~ Ludwigsburg, Germany ~ October 23 - 25, 2018";
+      $content['button_text'] = "Register Today!";
+      $content['button_url'] = $campaign;
 
-    $campaign = "";
-    $content['body'] ="";
-    $content['banner_styles'] = "";
-
-    if ((time() >= strtotime("2018/02/26") && time() < strtotime("2018/04/05")) || (time() >= strtotime("2018/04/30") && time() < strtotime("2018/05/11"))) {
-      $content['body'] ="Register now for FOSS4G NA 2018 ~ St. Louis, Missouri ~ May 14 - 17, 2018";
-      $campaign = "PROMO_F4G2018_DOWNLOADS_PAGE";
+      // Create the ad
+      $Ad = new Ad();
+      $Ad->setTitle('Downloads banner ad');
+      $Ad->setCampaign($campaign);
+      $Ad->setFormat("html");
+      $Ad->setHtml('tpl/downloadsBannerAd.tpl.php', $content);
+      $Ad->setType('paid');
+      $Ad->setWeight('100');
+      $this->newAd($Ad);
     }
-
-    if ((time() >= strtotime("2018/04/16") && time() < strtotime("2018/04/30")) || (time() >= strtotime("2018/05/14") && time() < strtotime("2018/06/13"))) {
-      $content['body'] ="Register now for EclipseCon France 2018 ~ Toulouse, France ~ June 13 - 14, 2018";
-      $campaign = "PROMO_ECF2018_DOWNLOADS_PAGE";
-    }
-
-    $content['button_text'] = "Register Today!";
-    $content['button_url'] = $campaign;
-
-    // Create the ad
-    $Ad = new Ad();
-    $Ad->setTitle('Downloads banner ad');
-    $Ad->setCampaign($campaign);
-    $Ad->setFormat("html");
-    $Ad->setHtml('tpl/downloadsBannerAd.tpl.php', $content);
-    $Ad->setType('paid');
-    $Ad->setWeight('100');
-    $this->newAd($Ad);
-
   }
 
   /**
@@ -55,14 +43,6 @@
    * @param $type - This variable determines help to determine which template file to use
    */
   protected function _build($layout = "", $type = "") {
-
-    // Check if the ad should be printed depending on the date
-    if ((time() >= strtotime("2018/02/26") && time() < strtotime("2018/04/05")) || (time() >= strtotime("2018/04/30") && time() < strtotime("2018/05/11"))) {
-      $this->output = $this->ad->getHtml();
-    }
-
-    if ((time() >= strtotime("2018/04/16") && time() < strtotime("2018/04/30")) || (time() >= strtotime("2018/05/14") && time() < strtotime("2018/06/13"))) {
-      $this->output = $this->ad->getHtml();
-    }
+    $this->output = $this->ad->getHtml();
   }
 }
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/eclipseAds.class.php b/eclipse.org-common/classes/ads/eclipseAds.class.php
index a101063..139ab64 100644
--- a/eclipse.org-common/classes/ads/eclipseAds.class.php
+++ b/eclipse.org-common/classes/ads/eclipseAds.class.php
@@ -1,14 +1,16 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2015, 2018 Eclipse Foundation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
  *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 require_once("ad.class.php");
 
@@ -19,7 +21,7 @@
  * @subpackage ads
  * @author: Christopher Guindon <chris.guindon@eclipse.org>
  */
-class EclipseAds{
+class EclipseAds {
 
  /**
   * The selected ad to display
@@ -46,12 +48,6 @@
   protected $source = "";
 
   /**
-   * The remote address of the user that will view the ad
-   * @var string
-   */
-  protected $remote_addr = "";
-
-  /**
    * The total weight of all ads
    * @var int
    */
@@ -65,14 +61,13 @@
     if ($source != "") {
       $this->source =  $source;
     }
-    $this->remote_addr = @gethostbyaddr($_SERVER['REMOTE_ADDR']);
   }
 
   /**
    * The ad builder, this funciton is ussually overwritten in a parent class
    * @return string
    */
-  protected function _build($layout = "", $type = "") {
+  protected function _build($layout = "", $type = "", $impression_id = "") {
     return "";
   }
 
@@ -134,12 +129,13 @@
         return "";
       }
       $campaign = $this->ad->getCampaign();
+      $impression_id = "";
       if (!empty($this->ad) && $campaign != "") {
-        $CampaignImpression = new CampaignImpression($campaign, $this->source, $this->remote_addr);
-        $CampaignImpression->recordImpression();
+        $CampaignImpression = new CampaignImpression($campaign);
+        $impression_id = $CampaignImpression->recordImpression();
       }
-      $this->_build($layout, $this->ad->getType());
+      $this->_build($layout, $this->ad->getType(), $impression_id);
     }
-    print $this->output;
+    return $this->output;
   }
 }
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/promoAds.class.php b/eclipse.org-common/classes/ads/promoAds.class.php
deleted file mode 100644
index 4f6933d..0000000
--- a/eclipse.org-common/classes/ads/promoAds.class.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-require_once("eclipseAds.class.php");
-
-/**
- * PromoAds
- */
-class PromoAds extends EclipseAds {
-
-  public function __construct($source = "") {
-    parent::__construct($source);
-
-    // PAID
-
-    // Froglogic
-    $Ad = new Ad();
-    $Ad->setTitle('FrogLogic');
-    $Ad->setUrl('https://www.eclipse.org/go/PAID_FROGLOGIC');
-    $Ad->setImage('/membership/promo/images/froglogic.gif');
-    $Ad->setType('paid');
-    $Ad->setWeight('9');
-    $this->newAd($Ad);
-
-    // JRebel
-    $Ad = new Ad();
-    $Ad->setTitle('JREBEL');
-    $Ad->setUrl('https://www.eclipse.org/go/PAID_JREBEL_A');
-    $Ad->setImage('/membership/promo/images/O4E-200x200-banner-1.jpg');
-    $Ad->setType('paid');
-    $Ad->setWeight('9');
-    $this->newAd($Ad);
-
-    // OTHER ADS
-
-    // CA
-    $Ad = new Ad();
-    $Ad->setTitle('CA');
-    $Ad->setUrl('/membership/showMember.php?member_id=655');
-    $Ad->setImage('/membership/scripts/get_image.php?size=small&id=655');
-    $Ad->setType('strategic');
-    $Ad->setWeight('13');
-    $this->newAd($Ad);
-
-    // Oracle
-    $Ad = new Ad();
-    $Ad->setTitle('Oracle');
-    $Ad->setUrl('https://www.eclipse.org/go/PROMO_ORACLE');
-    $Ad->setImage('/membership/promo/images/oepe_ad_200x200.jpg');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('13');
-    $this->newAd($Ad);
-
-    // Actuate
-    $Ad = new Ad();
-    $Ad->setTitle('Actuate');
-    $Ad->setUrl('https://www.eclipse.org/go/ACTUATEBP_B');
-    $Ad->setImage('/membership/promo/images/actuate_puzzle_200x200.png');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('13');
-    $this->newAd($Ad);
-
-    // IBM
-    $Ad = new Ad();
-    $Ad->setTitle('IBM');
-    $Ad->setUrl('https://www.eclipse.org/go/IBM_JAZZ');
-    $Ad->setImage('/membership/promo/images/ibm200x200-eclipse_orion.png');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('13');
-    $this->newAd($Ad);
-
-    // SAP
-    $Ad = new Ad();
-    $Ad->setTitle('SAP');
-    $Ad->setUrl('https://www.eclipse.org/go/PROMO_SAP');
-    $Ad->setImage('/membership/promo/images/sap200x200.jpg');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('13');
-    $this->newAd($Ad);
-
-    // Itemis
-    $Ad = new Ad();
-    $Ad->setTitle('Itemis');
-    $Ad->setUrl('https://www.eclipse.org/go/PROMO_ITEMIS');
-    $Ad->setImage('/membership/promo/images/xtext_200x200.gif');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('5.5');
-    $this->newAd($Ad);
-
-    // Obeo
-    $Ad = new Ad();
-    $Ad->setTitle('Obeo');
-    $Ad->setUrl('https://www.eclipse.org/go/PROMO_OBEO');
-    $Ad->setImage('/membership/promo/images/obeo_sirius.png');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('5.5');
-    $this->newAd($Ad);
-
-    //Eclipsecon
-    $Ad = new Ad();
-    $Ad->setTitle('Eclipsecon');
-    $Ad->setFormat('html');
-    $Ad->setHtml('tpl/eclipseconAd.tpl.php');
-    $Ad->setType('strat_ad');
-    $Ad->setWeight('20');
-    $this->newAd($Ad);
-
-  }
-
-/**
-   * Custom implementation of _build()
-   * @see EclipseAds::_build()
-   *
-   * @param $type - This variable determines help to determine which template file to use
-   */
-  protected function _build($layout = "", $type = "") {
-
-
-    if ($this->ad->getFormat() == "html") {
-      $this->output = $this->ad->getHtml();
-    }
-    $this->output = ob_get_clean();
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/promotedDownloads.class.php b/eclipse.org-common/classes/ads/promotedDownloads.class.php
deleted file mode 100644
index d563361..0000000
--- a/eclipse.org-common/classes/ads/promotedDownloads.class.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-require_once("eclipseAds.class.php");
-
-/**
- * PromotedDownloads
- */
-class PromotedDownloads extends EclipseAds {
-
-  public function __construct($source = "") {
-    parent::__construct($source);
-
-    // Note: 1 slot = 20
-    //       Total = 100
-
-    // IBM B // Keep this Ad for futur reference
-    /*$Ad = new Ad();
-    $Ad->setTitle('Use your Eclipse IDE to build in the cloud');
-    $Ad->setUrl('//bs.serving-sys.com/BurstingPipe/adServer.bs?cn=tf&c=20&mc=click&pli=17277852&PluID=0&ord=[timestamp]');
-    $Ad->setScriptUrl('//bs.serving-sys.com/BurstingPipe/adServer.bs?cn=rsb&c=28&pli=17255646&PluID=0&w=32&h=32&ord=[timestamp]');
-    $Ad->setIframeUrl('//bs.serving-sys.com/BurstingPipe/adServer.bs?cn=brd&FlightID=17255646&Page=&PluID=0&Pos=1663007610');
-    $Ad->setIframeImage('//bs.serving-sys.com/BurstingPipe/adServer.bs?cn=bsr&FlightID=17255646&Page=&PluID=0&Pos=1663007610');
-    $Ad->setBody('Love Eclipse? Want to move to Cloud? Bluemix + Eclipse make it easy. Sign up to begin building today!');
-    $Ad->setImage('/downloads/images/bluemix-logo-32x-promoted-download.png');
-    $Ad->setCampaign('PROMO_DOWNLOAD_IBM_B');
-    $Ad->setWeight(10);
-    $Ad->setType('ibm');
-    $this->newAd($Ad);*/
-
-    // EMPTY
-    $Ad = new Ad();
-    $Ad->setTitle('EMPTY');
-    $Ad->setBody("EMPTY");
-    $Ad->setImage("EMPTY");
-    $Ad->setCampaign('EMPTY');
-    $Ad->setUrl("https://");
-    $Ad->setWeight(60);
-    $Ad->setType('empty');
-    $this->newAd($Ad);
-
-    // JREBEL
-    $Ad = new Ad();
-    $Ad->setTitle('JRebel for Eclipse IDE');
-    $Ad->setBody('See Java Code Changes Instantly. Save Time. Reduce Stress. Finish Projects Faster!');
-    $Ad->setImage('/downloads/images/JRebel-42x42-dark.png');
-    $Ad->setCampaign('PROMO_DOWNLOAD_JREBEL');
-    $Ad->setUrl("https://www.eclipse.org/go/" . $Ad->getCampaign());
-    $Ad->setWeight(20);
-    $Ad->setType('default');
-    $this->newAd($Ad);
-
-    // YATTA
-    $Ad = new Ad();
-    $Ad->setTitle('Yatta Launcher for Eclipse');
-    $Ad->setBody('Install, launch, and share your Eclipse IDE. Stop configuring. Start Coding.');
-    $Ad->setImage('/downloads/images/launcherIcon42.png');
-    $Ad->setCampaign('PROMO_DOWNLOAD_YATTA');
-    $Ad->setUrl("https://www.eclipse.org/go/" . $Ad->getCampaign());
-    $Ad->setWeight(20);
-    $Ad->setType('default');
-    $this->newAd($Ad);
-  }
-
-  /**
-   * Custom implementation of _build()
-   * @see EclipseAds::_build()
-   *
-   * @param $type - This variable determines help to determine which template file to use
-   */
-  protected function _build($layout = "", $type = "") {
-
-    ob_start();
-
-    // Layout A is default
-    $tpl = "tpl/promotedDownloadsLayoutA.tpl.php";
-    if ($type == "ibm") {
-      $tpl = "tpl/promotedDownloadsIBMLayoutA.tpl.php";
-    }
-
-    // if Layout B is specified
-    if ($layout == 'layout_b'){
-      $tpl = "tpl/promotedDownloadsLayoutB.tpl.php";
-      if ($type == "ibm") {
-        $tpl = "tpl/promotedDownloadsIBMLayoutB.tpl.php";
-      }
-    }
-    include($tpl);
-    $this->output = ob_get_clean();
-  }
-}
-
diff --git a/eclipse.org-common/classes/ads/promotedPlugin.class.php b/eclipse.org-common/classes/ads/promotedPlugin.class.php
deleted file mode 100644
index 250ee92..0000000
--- a/eclipse.org-common/classes/ads/promotedPlugin.class.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-require_once("eclipseAds.class.php");
-
-/**
- * PromotedPlugin
- *
- * @package eclipse.org-common
- * @subpackage ads
- * @author: Christopher Guindon <chris.guindon@eclipse.org>
- */
-class PromotedPlugin extends EclipseAds {
-
-  /**
-   * Constructor
-   *
-   * @param string $source
-   *   The description of the location of the ad.
-   */
-  public function __construct($source = "") {
-    parent::__construct($source);
-
-    /* Note: Keeping the next block as a reference.
-             If we decide to add the promoted plugins back to display */
-
-    /*$Ad = new Ad();
-    $Ad->setTitle('Java 9 Support (Beta)');
-    $this->_setMarketplaceNodeId('2393593', $Ad);
-    $Ad->setBody('Early access to Java 9 support for Mars.');
-    $Ad->setImage('/downloads/images/promoted_listings/default.png');
-    $Ad->setCampaign('PP_JAVA9');
-    $Ad->setWeight(50);
-    $this->newAd($Ad);*/
-
-  }
-
-  /**
-   * Custom implementation of _build()
-   * @see EclipseAds::_build()
-   */
-  protected function _build($layout = "", $type = "") {
-    ob_start();
-    include("tpl/promotedPlugin.tpl.php");
-    $this->output = ob_get_clean();
-  }
-
-  /**
-   * Set Links for a promoted plugin
-   * @param string $id
-   * @param unknown $Ad
-   */
-  protected function _setMarketplaceNodeId($id = '', &$Ad) {
-    $Ad->setUrl('http://marketplace.eclipse.org/marketplace-client-intro?mpc_install=' . $id);
-    $Ad->setUrl2('http://marketplace.eclipse.org/node/' . $id);
-  }
-
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/promotions.class.php b/eclipse.org-common/classes/ads/promotions.class.php
new file mode 100644
index 0000000..da35b52
--- /dev/null
+++ b/eclipse.org-common/classes/ads/promotions.class.php
@@ -0,0 +1,280 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Christopher Guindon (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+require_once (dirname(__FILE__) . "/../membership/membershipImage.class.php");
+require_once ("campaignImpression.class.php");
+
+/**
+ *
+ * Display paid promotions on Eclipse web properties
+ *
+ * @author chrisguindon
+ */
+class Promotions {
+
+  /**
+   * Eclipse Advertisements
+   *
+   * 1. Paid ads should split 40% of the total impressions
+   * 2. EclipseCon should take 10% of the total impressions
+   * 3. Members ads should split the remaning 50%.
+   *
+   * @return array $retVal
+   */
+  static public function getPromos($filter = array()) {
+    $promos = array();
+
+    /**
+     * PAID ads (30%)
+     */
+    $promos[] = array(
+      'url' => 'PAID_FROGLOGIC_BANNER_1',
+      'imageurl' => '/membership/promo/images/banner_1_froglogic.png',
+      'memberName' => 'FrogLogic',
+      'type' => 'paid',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PAID_FROGLOGIC_BANNER_2',
+      'imageurl' => '/membership/promo/images/banner_2_froglogic_proven_java_learn_more.png',
+      'memberName' => 'FrogLogic',
+      'type' => 'paid',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_KONDUIT',
+      'imageurl' => '/membership/promo/images/konduit.jpg',
+      'memberName' => 'Konduit',
+      'type' => 'strat_ad',
+      'weight' => 5
+    );
+
+    // Strategic Member Ads
+    $promos[] = array(
+      'url' => 'PROMO_ORACLE',
+      'imageurl' => '/membership/promo/images/oepe_ad_200x200.jpg',
+      'memberName' => 'Oracle',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'IBM_JAZZ',
+      'imageurl' => '/membership/promo/images/ibm200x200-ibm_cloud.jpg',
+      'memberName' => 'IBM',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+    $promos[] = array(
+      'url' => 'PROMO_SAP',
+      'imageurl' => '/membership/promo/images/sap200x200.jpg',
+      'memberName' => 'SAP',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_OBEO',
+      'imageurl' => '/membership/promo/images/Sirius_ad_200.png',
+      'memberName' => 'Obeo',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_CEA',
+      'imageurl' => '/membership/promo/images/PapyrusCEA.gif',
+      'memberName' => 'CEA',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_FUJITSU',
+      'imageurl' => '/membership/promo/images/fujitsu_200px.jpg',
+      'memberName' => 'Fujitsu',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_RED_HAT',
+      'imageurl' => '/membership/promo/images/redhat-ad.jpg',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_FOKUS',
+      'imageurl' => '/membership/promo/images/fokus_promo.jpg',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_HUAWEI',
+      'imageurl' => '/membership/promo/images/huawei-ad-eclipse-hdc.jpg',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 5
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_EUROPEAN_RESEARCH_CASE_STUDY_2020',
+      'imageurl' => '/membership/promo/images/european-research-innovation-case-studies.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_CEDALO_CASE_STUDY',
+      'imageurl' => '/membership/promo/images/promo_cedalo_case_study.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_ENABLING_TRANSFORMATION',
+      'imageurl' => '/membership/promo/images/enabling_digital_transformation.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_JAKARTA_EE_DEV_SURVEY_2020',
+      'imageurl' => '/membership/promo/images/jakarta_ee_developer_survey_2020.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 4
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_JAKARTAONE_REGISTER_TODAY',
+      'imageurl' => '/membership/promo/images/jakartaone-register-today.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_IOT_DEV_SURVEY_2020',
+      'imageurl' => '/membership/promo/images/iot_dev_survey_2020.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    $promos[] = array(
+      'url' => 'PROMO_JAKARTA_EE_YOUTUBE',
+      'imageurl' => '/membership/promo/images/jakarta_ee_youtube_ad.png',
+      'memberName' => 'EclipseFoundation',
+      'type' => 'strat_ad',
+      'weight' => 6
+    );
+
+    if (!empty($filter)) {
+      $filter_promo = array();
+      foreach ($promos as $ad) {
+        if (in_array($ad['type'], $filter)) {
+          $filter_promo[] = $ad;
+        }
+      }
+      return $filter_promo;
+    }
+
+    return $promos;
+  }
+
+  /**
+   * Return promo HTML
+   *
+   * @return string
+   */
+  static public function output($filter = array()) {
+    $promos = self::getPromos($filter);
+    $ad = (isset($_GET['ad_id']) && is_numeric($_GET['ad_id']) && !empty($promos[$_GET['ad_id']])) ? $promos[$_GET['ad_id']] : self::_array_rand_weighted($promos);
+    if (empty($ad['type'])) {
+      return "";
+    }
+
+    if ($ad['type'] == 'strategic') {
+      return self::_buildStrategicMemberAd($ad);
+    }
+    return self::_buildAd($ad);
+  }
+
+  /**
+   * Build Strategic Member ad
+   *
+   * @param unknown $array
+   * @return string
+   */
+  static private function _buildStrategicMemberAd($array) {
+    $mimg = new MemberImage();
+    list($width, $height) = $mimg->getsmall_image($array['memberID']);
+
+    // check for errors ( -1 in both means something bad happened getting the
+    // image details)
+    if ($width >= 1 && $height >= 1) {
+      $heightText = 'height="' . $height . '" ';
+      return '<div class="eclipsefnd-ad ad-strategic ad-strategic-frontpage"><a href="/membership/showMember.php?member_id=' . $array['memberID'] . '" rel="nofollow" style="background-image: url(\'/membership/scripts/get_image.php?size=small&id=' . $array['memberID'] . '\')">' . $array['memberName'] . '</a></div>';
+    }
+    return "";
+  }
+
+  /**
+   * Build stadard promo ad
+   * @param unknown $array
+   * @return string
+   */
+  static private function _buildAd($array) {
+    if (empty($array) || empty($array['url']) || empty($array['imageurl']) || empty($array['memberName'])) {
+      return "";
+    }
+    $CampaignImpression = new CampaignImpression($array['url']);
+    $impression_id = $CampaignImpression->recordImpression();
+    return '<div class="eclipsefnd-ad ad-strategic ad-strategic-default"><a href="/go/' . $array['url'] . '?impression_id=' . $impression_id . '" rel="nofollow" style="background-image: url(\'' . $array['imageurl'] . '\')">' . $array['memberName'] . '</a></div>';
+  }
+
+  /**
+   * Select an add based of #weight value
+   *
+   * @param unknown $values
+   *
+   * @return unknown
+   */
+  static private function _array_rand_weighted($values) {
+    if (empty($values)) {
+      return array();
+    }
+    $totalWeight = 0;
+    foreach ($values as $rr) {
+      $totalWeight += $rr['weight'];
+    }
+    $r = mt_rand(1, $totalWeight);
+    foreach ($values as $item) {
+      if ($r <= $item['weight'])
+        return $item;
+      $r -= $item['weight'];
+    }
+  }
+
+}
diff --git a/eclipse.org-common/classes/ads/redirector.class.php b/eclipse.org-common/classes/ads/redirector.class.php
new file mode 100644
index 0000000..26f9ebd
--- /dev/null
+++ b/eclipse.org-common/classes/ads/redirector.class.php
@@ -0,0 +1,232 @@
+<?php
+/**
+ * Copyright (c) 2015, 2018 Eclipse Foundation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/app.class.php");
+
+/**
+ * Redirector for Eclipse campaign manager
+ *
+ * Based off the work from Denis Roy (/go/redirector.php)
+ *
+ * @author chrisguindon
+ */
+class Redirector {
+
+  /**
+   * Campaign Tag
+   *
+   * @var string
+   */
+  protected $tag = "";
+
+  /**
+   * Campaign SubTag
+   *
+   * @var string
+   */
+  protected $subtag = "";
+
+  /**
+   * $impression_click_id from CampaignImpressions
+   *
+   * @var numeric
+   */
+  protected $impression_click_id = "";
+
+  /**
+   * Redirect action
+   *
+   * Browser will be redirected,
+   * otherwise an error page is shown
+   */
+  function redirect() {
+    if ($result = $this->getCampaign()) {
+
+      // redirect the browser now
+      $sub_tag = $this->getSubTag();
+      if (!empty($sub_tag)) {
+        header("Location: " . $result['url'] . "?" . $sub_tag);
+      }
+      else {
+        header("Location: " . $result['url']);
+      }
+
+      // Record click
+      $this->_insertCampaignClicks();
+      // Exit otherwise the server will try to
+      // send out the error page
+      exit();
+    }
+    $this->_showErrorPage();
+  }
+
+  /**
+   * Get Campaign based off $tag
+   *
+   * @return boolean|mysql_query()
+   */
+  public function getCampaign() {
+    $App = new App();
+    $tag = $this->getTag();
+    if (empty($tag)) {
+      return FALSE;
+    }
+    $sql = "SELECT TargetUrl as url FROM Campaigns WHERE CampaignKey = " . $App->returnQuotedString($App->sqlSanitize($tag));
+    $result = $App->eclipse_sql($sql);
+    if ($row = mysql_fetch_assoc($result)) {
+      return $row;
+    }
+    return FALSE;
+  }
+
+
+  /**
+   * Get impressionID
+   *
+   * @return numeric
+   */
+  public function getImpressionId() {
+    return $this->impression_click_id;
+  }
+
+  /**
+   * Set ImpressionID
+   *
+   * @param numeric $impression_click_id
+   *
+   * @return boolean
+   */
+  public function setImpressionId($impression_click_id = "") {
+    if (ctype_alnum($impression_click_id) && (strlen($impression_click_id) >= 32 && strlen($impression_click_id) <= 64)) {
+      $this->impression_click_id = $impression_click_id;
+      return TRUE;
+    }
+
+    $this->impression_click_id = NULL;
+    return FALSE;
+  }
+
+  /**
+   * Set tags and sub tags
+   *
+   * @param string $tag
+   *
+   * @return boolean
+   */
+  public function setTags($tag = "") {
+    if (empty($tag) || !is_string($tag)) {
+      return FALSE;
+    }
+    $tag = strtoupper($tag);
+    $x = stripos($tag, '@');
+    if ($x !== FALSE) {
+      $subtag = substr($tag, $x + 1);
+      // strip potentially bad characters from file
+      $this->subtag = preg_replace('/["\'?%$#@!;*&]/i', '', $subtag);
+      $tag = substr($tag, 0, $x);
+    }
+
+    // strip potentially bad characters from file
+    $this->tag = preg_replace('/["\'?%$#@!;*&]/i', '', $tag);
+    return TRUE;
+  }
+
+  /**
+   * Get tag
+   *
+   * @return string
+   */
+  public function getTag() {
+    return $this->tag;
+  }
+
+  /**
+   * Get subtag
+   *
+   * @return string
+   */
+  public function getSubTag() {
+    return $this->subtag;
+  }
+
+  /**
+   * Insert Campaign Clicks
+   *
+   * @return mysql_query()
+   */
+  protected function _insertCampaignClicks() {
+    $App = new App();
+    $tag = $this->getTag();
+
+    if (empty($tag)) {
+      return FALSE;
+    }
+
+    if (rand(0, 1000) < 1) {
+      // 1 of every 1,000 hits (0.1%) will clean up
+      $deleteSql = "DELETE LOW_PRIORITY FROM CampaignClicks WHERE TimeClicked < DATE_SUB(NOW(), INTERVAL 1 YEAR)";
+      $App->eclipse_sql($deleteSql);
+    }
+
+    $ip =  $App->anonymizeIP($App->getRemoteIPAddress());
+    $ip = (!empty($ip)) ? $App->returnQuotedString($App->sqlSanitize($ip)) : 'NULL';
+
+    $subtag = $this->getSubTag();
+    $subtag = (!empty($subtag)) ? $App->returnQuotedString($App->sqlSanitize($subtag)) : 'NULL';
+
+   // Make sure we have a valid impression Id
+    $impression_click_id = $this->getImpressionId();
+    $impression_click_id = (!empty($impression_click_id)) ? $App->returnQuotedString($App->sqlSanitize($impression_click_id)) : 'NULL';
+
+    $sql = "INSERT /* /redirector.class.php */ INTO CampaignClicks (
+            CampaignKey,
+            SubKey,
+            HostName,
+            ImpressionClickID,
+            TimeClicked
+            ) VALUES (
+            " . $App->returnQuotedString($App->sqlSanitize($tag)) . ",
+            " . $subtag . ",
+            " . $ip . ",
+            " . $impression_click_id . ",
+            NOW())";
+
+    return $App->eclipse_sql($sql);
+  }
+
+  /**
+   * Serve Error/Expired link page
+   */
+  protected function _showErrorPage() {
+    $html = '<div id="maincontent">
+        <div id="midcolumn">
+          <h1>Expired Link</h1>
+      <p> There was an error processing this link.  It is likely you are following an old link to an expired campaign activity.  For example,
+      you may have clicked on a link to a survey that is now closed or to a special offer that is no longer applicable.  If you believe
+      this link should work, please contact the source of the link.  While you are here, please browse some of our website by
+      clicking on the appropriate tab at the top of the page.
+      </p>
+
+      <hr class="clearer" />
+      </div>
+    </div>';
+    $App = new App();
+    $Theme = $App->getThemeClass();
+    $Theme->setHtml($html);
+    $Theme->generatePage();
+    exit();
+  }
+
+
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/tpl/ad_reports.tpl.php b/eclipse.org-common/classes/ads/tpl/ad_reports.tpl.php
index 2b32727..b421ea6 100644
--- a/eclipse.org-common/classes/ads/tpl/ad_reports.tpl.php
+++ b/eclipse.org-common/classes/ads/tpl/ad_reports.tpl.php
@@ -1,3 +1,18 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Christopher Guindon (Eclipse Foundation)  - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+?>
+
 <?php $impressions = $this->getImpressions();?>
 <form method="POST" action="">
   <input name="state" value="exportCsv" type="hidden">
diff --git a/eclipse.org-common/classes/ads/tpl/campaignManager.tpl.php b/eclipse.org-common/classes/ads/tpl/campaignManager.tpl.php
index 45a2010..a992c6e 100644
--- a/eclipse.org-common/classes/ads/tpl/campaignManager.tpl.php
+++ b/eclipse.org-common/classes/ads/tpl/campaignManager.tpl.php
@@ -1,15 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2007-2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Donald Smith (Eclipse Foundation) - initial API and implementation
- *    Eric Poirier (Eclipse Foundation)
- *******************************************************************************/
+ *   Donald Smith (Eclipse Foundation) - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 print $this->page_header_html; ?>
 
diff --git a/eclipse.org-common/classes/ads/tpl/campaign_view_campaigns.tpl.php b/eclipse.org-common/classes/ads/tpl/campaign_view_campaigns.tpl.php
index c5dd444..2e264a7 100644
--- a/eclipse.org-common/classes/ads/tpl/campaign_view_campaigns.tpl.php
+++ b/eclipse.org-common/classes/ads/tpl/campaign_view_campaigns.tpl.php
@@ -1,15 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2007-2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation)
- *******************************************************************************/
-
+ *   Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 // Check to see if a person or a group as been selected
 $selection = $this->getCampaignByUserOrGroup();
diff --git a/eclipse.org-common/classes/ads/tpl/campaign_view_clicks.tpl.php b/eclipse.org-common/classes/ads/tpl/campaign_view_clicks.tpl.php
index a1361ff..7c58244 100644
--- a/eclipse.org-common/classes/ads/tpl/campaign_view_clicks.tpl.php
+++ b/eclipse.org-common/classes/ads/tpl/campaign_view_clicks.tpl.php
@@ -1,15 +1,17 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2007-2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation)
- *******************************************************************************/
-
+ *   Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 // VIEW CLICKS
 ?>
 <div class="row">
diff --git a/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutA.tpl.php b/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutA.tpl.php
deleted file mode 100644
index 297722d..0000000
--- a/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutA.tpl.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<span class="downloads-logo vertical-align">
-<script src="<?php print $this->ad->getScriptUrl();?>"></script>
-<noscript>
-  <a href="<?php print $this->ad->getIframeUrl;?>" target="_blank">
-    <img src="<?php print $thi->ad->getIframeImage;?>" width=32 height=32 alt="Click Here" border=0>
-  </a>
-</noscript>
-</span>
-<p><?php print $this->ad->getBody();?></p>
-<p class="orange small"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</p>
-<p class="visible-xs visible-sm"><a href="<?php print $this->ad->getUrl();?>" class="btn btn-warning btn-xs">Get it</a></p>
-<p class="visible-xs visible-sm downloads-items-hover-box-links"><a href="<?php print $this->ad->getUrl();?>">Learn More</a></p>
-<div class="downloads-items-hover-box">
-  <h4 class="downloads-items-header"><?php print $this->ad->getTitle();?></h4>
-  <p class="downloads-items-hover-box-text"><?php print $this->ad->getBody();?></p>
-  <p><a href="<?php print $this->ad->getUrl();?>" class="btn btn-warning btn-xs"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</a></p>
-  <p class="downloads-items-hover-box-links"><a href="<?php print $this->ad->getUrl();?>">Learn More</a></p>
-</div>
diff --git a/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutB.tpl.php b/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutB.tpl.php
deleted file mode 100644
index 6b6f979..0000000
--- a/eclipse.org-common/classes/ads/tpl/promotedDownloadsIBMLayoutB.tpl.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<div class="package-row clearfix promo">
-  <div class="row vertical-align-min-md">
-    <div class="col-xs-3 icon">
-      <!-- iframe/script/href/image tag -->
-      <script src="<?php print $this->ad->getScriptUrl();?>"></script>
-      <noscript>
-        <a href="<?php print $this->ad->getIframeUrl;?>" target="_blank">
-          <img src="<?php print $thi->ad->getIframeImage;?>" width=32 height=32 alt="Click Here" border=0>
-        </a>
-      </noscript>
-    </div>
-    <div class="col-sm-13 text xs-sm-text-center">
-      <h3>
-        <a href="<?php print $this->ad->getUrl();?>" target="_blank"><?php print $this->ad->getTitle();?>
-          <img src="<?php print $this->ad->getImage();?>" width=1 height=1 alt=" " border=0>
-        </a>
-      </h3>
-      <p><?php print $this->ad->getBody();?></p>
-    </div>
-    <div class="col-sm-8 download">
-      <div class="col-sm-9 downloadLink-icon"><i class="fa fa-download"></i></div>
-      <div class="col-sm-15 downloadLink-content">
-        <div class="text-center">
-          <p>
-            <a class="orange" href="<?php print $this->ad->getUrl();?>" target="_blank">
-              <i class="fa fa-star"></i><br/>Promoted<br/>Download</a><br/></p>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutA.tpl.php b/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutA.tpl.php
deleted file mode 100644
index 9bf68e3..0000000
--- a/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutA.tpl.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<span class="downloads-logo vertical-align"><img height="50" alt="Promoted Downloads" src="<?php print $this->ad->getImage();?>"></span>
-<!--<h3 class="downloads-items-header">Deploy IBM Bluemix</h3>-->
-<p><?php print $this->ad->getBody();?></p>
-<p class="orange small"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</p>
-<p class="visible-xs visible-sm"><a href="<?php print $this->ad->getUrl();?>" class="btn btn-warning btn-xs">Get it</a></p>
-<p class="visible-xs visible-sm downloads-items-hover-box-links"><a href="<?php print $this->ad->getUrl();?>">Learn More</a></p>
-<div class="downloads-items-hover-box">
-  <h4 class="downloads-items-header"><?php print $this->ad->getTitle();?></h4>
-  <p class="downloads-items-hover-box-text"><?php print $this->ad->getBody();?></p>
-  <p><a href="<?php print $this->ad->getUrl();?>" class="btn btn-warning btn-xs"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</a></p>
-  <p class="downloads-items-hover-box-links"><a href="<?php print $this->ad->getUrl();?>">Learn More</a></p>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutB.tpl.php b/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutB.tpl.php
deleted file mode 100644
index 8ac3eed..0000000
--- a/eclipse.org-common/classes/ads/tpl/promotedDownloadsLayoutB.tpl.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<div class="package-row clearfix zebra promo">
-  <div class="row vertical-align-min-md">
-    <div class="col-sm-3 icon"><img src="<?php print $this->ad->getImage();?>" width="42" height="42" alt="<?php print $this->ad->getTitle();?>"/></div>
-    <div class="col-sm-13 text xs-sm-text-center">
-      <h3 class="title">
-        <a class="promo-title" href="//eclipse.org/go/<?php print $this->ad->getCampaign();?>" title="<?php print $this->ad->getTitle();?>"><?php print $this->ad->getTitle();?></a>
-      </h3>
-      <p><?php print $this->ad->getBody();?></p>
-    </div>
-
-    <div class="col-sm-8 download">
-      <div class="col-sm-9 downloadLink-icon"><i class="fa fa-download"></i></div>
-        <div class="col-sm-15 downloadLink-content">
-          <div class="text-center">
-            <p>
-              <a class="orange" href="//eclipse.org/go/<?php print $this->ad->getCampaign();?>" title="<?php print $this->ad->getTitle();?>">
-                <span class="text-center"><i class="fa fa-star"></i></span><br/>Promoted<br/>Download
-              </a>
-            </p>
-          </div>
-        </div>
-    </div>
-  </div>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/ads/tpl/promotedPlugin.tpl.php b/eclipse.org-common/classes/ads/tpl/promotedPlugin.tpl.php
deleted file mode 100644
index 75af8c0..0000000
--- a/eclipse.org-common/classes/ads/tpl/promotedPlugin.tpl.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-<div class="promoted-plugin">
-  <a href="<?php print $this->ad->getUrl2();?>">
-    <span class="header clearfix">
-      <h3><i class="fa fa-star">&nbsp;</i> Promoted Plugin</h3>
-    </span>
-    <span class="content clearfix">
-      <span class="col-xs-8 pp-image">
-        <img src="<?php print $this->ad->getImage();?>" class="img-responsive"/>
-      </span>
-      <span class="col-xs-16 pp-content">
-        <span class="pp-title"><?php print $this->ad->getTitle();?></span>
-        <span class="pp-text"><?php print $this->ad->getBody();?></span>
-      </span>
-    </span>
-  </a>
-  <a href="<?php print $this->ad->getUrl();?>" class="drag">
-    <span class="download clearfix drag_installbutton">
-      <i class="fa fa-download pull-left"></i>
-      <span class="padding-top-10" style="display:block">INSTALL NOW</span>
-      <span class="tooltip show-right"><span class="h3">Drag to Install!</span><br/>Drag to your running Eclipse workspace.</span>
-    </span>
-  </a>
-</div>
diff --git a/eclipse.org-common/classes/captcha/captcha.class.php b/eclipse.org-common/classes/captcha/captcha.class.php
deleted file mode 100644
index 656153d..0000000
--- a/eclipse.org-common/classes/captcha/captcha.class.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-require_once("recaptcha.class.php");
-
-class Captcha extends ReCaptcha {
-  function __construct($ssl = TRUE) {
-    parent::__construct($ssl);
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/captcha/recaptcha.class.php b/eclipse.org-common/classes/captcha/recaptcha.class.php
deleted file mode 100644
index d18d663..0000000
--- a/eclipse.org-common/classes/captcha/recaptcha.class.php
+++ /dev/null
@@ -1,259 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-
-require_once ("recaptchaMailHide.class.php");
-
-define("RECAPTCHA_API_SERVER", "www.google.com/recaptcha/api");
-
-define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
-
-class ReCaptcha extends ReCaptchaMailHide {
-
-  private $pubkey = "";
-
-  private $privkey = "";
-
-  private $challenge = NULL;
-
-  private $response = NULL;
-
-  private $use_ssl = TRUE;
-
-  private $server = "";
-
-  private $remoteip = "";
-
-  private $is_valid = FALSE;
-
-  private $error = "";
-
-  function __construct($ssl = TRUE) {
-    parent::__construct();
-    $this->pubkey = RECAPTCHA_PUBKEY;
-    $this->privkey = RECAPTCHA_PRIVKEY;
-
-    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
-      $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
-    }
-    else {
-      $ip = $_SERVER['REMOTE_ADDR'];
-    }
-
-    $this->remoteip = $ip;
-    $this->_use_ssl($ssl);
-  }
-
-  /**
-   * Gets error from reCAPTCHA.
-   *
-   * @return string
-   */
-  public function  get_error() {
-    return $this->error;
-  }
-
-  /**
-   * Gets the challenge HTML (javascript and non-javascript version).
-   *
-   * This is called from the browser, and the resulting reCAPTCHA HTML widget
-   * is embedded within the HTML form it was called from.
-   *
-   * @return string - The HTML to be embedded in the user's form.
-   */
-  public function get_html() {
-    if ($this->pubkey == NULL || $this->pubkey == '') {
-      die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
-    }
-
-    $errorpart = "";
-    if ($this->error) {
-      $errorpart = "&amp;error=" . $this->error;
-    }
-
-    return '<script type="text/javascript" src="'. $this->server . '/challenge?k=' . $this->pubkey . $errorpart . '"></script>
-
-    <noscript>
-        <iframe src="'. $this->server . '/noscript?k=' . $this->pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
-        <textarea name="challenge_field" rows="3" cols="40"></textarea>
-        <input type="hidden" name="response_field" value="manual_challenge"/>
-    </noscript>';
-  }
-
-  /**
-   * Verify if the captcha anwser was correct.
-   *
-   * @return bool
-   */
-  public function validate() {
-    $this->verify_answer();
-    return $this->is_valid;
-  }
-
-  /**
-    * Calls an HTTP POST function to verify if the user's guess was correct
-    *
-    * @param string $challenge
-    * @param string $response
-    * @param array $extra_params an array of extra variables to post to the server
-    *
-    * @return bool
-    */
-  public function verify_answer($challenge = NULL, $response = NULL, $extra_params = array()) {
-    if ($this->privkey == null || $this->privkey == '') {
-      die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
-    }
-
-    if ($this->remoteip == null || $this->remoteip == '') {
-      die ("For security reasons, you must pass the remote ip to reCAPTCHA");
-    }
-
-    //discard spam submissions
-    if (!$this->_verify_spam($challenge, $response)) {
-      $this->is_valid = FALSE;
-      $this->error = 'incorrect-captcha-sol';
-      return FALSE;
-    }
-
-    $path = array_merge(array(
-      'privatekey' => $this->privkey,
-      'remoteip' => $this->remoteip,
-      'challenge' => $this->challenge,
-      'response' => $this->response
-    ), $extra_params);
-
-    $response = $this->_http_post(RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", $path);
-
-    $answers = explode("\n", $response[0]);
-
-    if (trim($answers[0]) == 'true') {
-      $this->is_valid = TRUE;
-      return TRUE;
-    }
-    else {
-      $this->is_valid = FALSE;
-      $this->error = $answers[1];
-    }
-
-    return FALSE;
-  }
-
-  /**
-   * Submits an HTTP POST to a reCAPTCHA server
-   *
-   * @param string $host
-   * @param string $path
-   * @param array $data
-   *
-   * @return array response
-   */
-  private function _http_post($host, $path, $data) {
-    $add_headers = array(
-      "Host: $host",
-    );
-
-    $cu = curl_init('https://' . $host . $path);
-    curl_setopt($cu, CURLOPT_POST, TRUE);
-    curl_setopt($cu, CURLOPT_RETURNTRANSFER, TRUE);
-    curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, 10);
-    curl_setopt($cu, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-    curl_setopt($cu, CURLOPT_USERAGENT, 'reCAPTCHA/PHP');
-    curl_setopt($cu, CURLOPT_POSTFIELDS, $data);
-    curl_setopt($cu, CURLOPT_HEADER, FALSE);
-    curl_setopt($cu, CURLOPT_HTTPHEADER, $add_headers);
-    curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, 30);
-
-    curl_setopt($cu, CURLOPT_SSL_VERIFYPEER, 1);
-    curl_setopt($cu, CURLOPT_SSL_VERIFYHOST, 2);
-
-    // Need to use eclipse.org proxy
-    curl_setopt($cu, CURLOPT_HTTPPROXYTUNNEL, TRUE);
-    curl_setopt($cu, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
-    curl_setopt($cu, CURLOPT_PROXY, 'proxy.eclipse.org:9899');
-
-    $response = curl_exec($cu);
-    if ($response === FALSE) {
-      die('Error connecting to ' . $host . '.');
-    }
-
-    $response = explode("\r\n\r\n", $response, 2);
-
-    return $response;
-}
-
-
-  /**
-   * Encodes the given data into a query string format
-   *
-   * @param $data - array of string elements to be encoded
-   *
-   * @return string - encoded request
-   */
-  private function _qsencode($data) {
-    $req = "";
-    foreach ($data as $key => $value ) {
-      $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
-    }
-
-    // Cut the last '&'
-    $req = substr($req,0,strlen($req)-1);
-    return $req;
-  }
-
-  /**
-   * Verify if the request is spam before posting to reCAPTCHA.
-   *
-   * @param string $challenge
-   * @param string $response
-   *
-   * @return boolean
-   */
-  private function _verify_spam($challenge = NULL, $response = NULL) {
-
-    $this->challenge = $challenge;
-    $this->response = $response;
-
-    if ((is_null($this->challenge) || empty($this->challenge)) && isset($_POST["recaptcha_response_field"])) {
-      $this->challenge = $_POST["recaptcha_challenge_field"];
-    }
-
-    if ((is_null($this->response) || empty($this->response)) && isset($_POST["recaptcha_response_field"])) {
-      $this->response = $_POST["recaptcha_response_field"];
-    }
-
-    if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) {
-      return FALSE;
-    }
-
-    return TRUE;
-  }
-
-  /**
-   * Set protocol for loading reCAPTCHA
-   *
-   * @param string $use_ssl
-   *
-   * @return boolean
-   */
-  private function _use_ssl($use_ssl = TRUE) {
-    $protocol =  "http://";
-    if (is_bool($use_ssl)) {
-      $this->use_ssl = $use_ssl;
-    }
-
-    if ($this->use_ssl) {
-      $protocol =  "https://";
-    }
-
-    $this->server = $protocol . RECAPTCHA_API_SERVER;
-    return $this->use_ssl;
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/captcha/recaptchaMailHide.class.php b/eclipse.org-common/classes/captcha/recaptchaMailHide.class.php
deleted file mode 100644
index fac0a7f..0000000
--- a/eclipse.org-common/classes/captcha/recaptchaMailHide.class.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-
-require_once("/home/data/httpd/eclipse-php-classes/system/captchacode.php");
-
-class ReCaptchaMailHide {
-
-  private $pubkey = "";
-
-  private $privkey = "";
-
-  function __construct() {
-    $this->pubkey = RECAPTCHA_MAILHIDE_PUBKEY;
-    $this->privkey = RECAPTCHA_MAILHIDE_PRIVKEY;
-  }
-
-  /**
-   * Gets html to display an email address given a public an private key.
-   * to get a key, go to:
-   *
-   * http://www.google.com/recaptcha/mailhide/apikey
-   *
-   * @param string $email
-   * @return string
-   */
-  public function get_mailhide_html($email) {
-    $emailparts = $this->_mailhide_email_parts($email);
-    $url = $this->get_mailhide_url($email);
-
-    return htmlentities($emailparts[0]) . "<a href='" . htmlentities($url) .
-      "' onclick=\"window.open('" . htmlentities($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities($emailparts[1]);
-  }
-
-  /**
-   * Gets the reCAPTCHA Mailhide url for a given email
-   *
-   * @param string $email
-   * @return string url
-   */
-  public function get_mailhide_url($email = "") {
-    if ($this->pubkey == '' || $this->pubkey == null || $this->privkey == "" || $this->privkey == null) {
-      die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
-           "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
-    }
-
-    $ky = pack('H*', $this->privkey);
-    $cryptmail = $this->_aes_encrypt($email, $ky);
-
-    return "http://www.google.com/recaptcha/mailhide/d?k=" . $this->pubkey . "&c=" . $this->_mailhide_urlbase64($cryptmail);
-  }
-
-  /**
-   * Prepare value for encryption.
-   *
-   * @param string $val
-   * @return string
-   */
-  protected function _aes_pad($val = "") {
-    $block_size = 16;
-    $numpad = $block_size - (strlen ($val) % $block_size);
-    return str_pad($val, strlen ($val) + $numpad, chr($numpad));
-  }
-
-  /**
-   * Encrypt value with mcrypt_encrypt().
-   *
-   * @param string $val
-   * @param string $ky
-   *
-   * @return string
-   */
-  private function _aes_encrypt($val = "", $ky = "") {
-    if (!function_exists ("mcrypt_encrypt")) {
-      die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
-    }
-    $mode = MCRYPT_MODE_CBC;
-    $enc = MCRYPT_RIJNDAEL_128;
-    $val = $this->_aes_pad($val);
-
-    return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
-  }
-
-  /**
-   * base64_encode mcrypt_encrypt value.
-   *
-   * @param string $x
-   *
-   * @return string
-   */
-  private function _mailhide_urlbase64($x = "") {
-    return strtr(base64_encode($x), '+/', '-_');
-  }
-
-  /**
-   * Gets the parts of the email to expose to the user.
-   *
-   * eg, given johndoe@example,com return ["john", "example.com"].
-   * the email is then displayed as john...@example.com
-   *
-   * @param string $email
-   *
-   * @return array
-   */
-  private function _mailhide_email_parts($email) {
-    $arr = preg_split("/@/", $email);
-
-    if (strlen ($arr[0]) <= 4) {
-      $arr[0] = substr($arr[0], 0, 1);
-    } else if (strlen($arr[0]) <= 6) {
-      $arr[0] = substr($arr[0], 0, 3);
-    } else {
-      $arr[0] = substr($arr[0], 0, 4);
-    }
-
-    return $arr;
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/directors/directors.class.php b/eclipse.org-common/classes/directors/directors.class.php
index af77dcb..4555099 100644
--- a/eclipse.org-common/classes/directors/directors.class.php
+++ b/eclipse.org-common/classes/directors/directors.class.php
@@ -16,6 +16,8 @@
 
   private $directors = array();
 
+  private $aisbl_directors = array();
+
   private $path_to_boardbio = "/org/foundation/boardbios";
 
   public function __construct(App $App) {
@@ -36,6 +38,19 @@
   }
 
   /**
+   * This function returns an array of AISBL directors with their bio
+   *
+   * @return array
+   *
+   */
+  public function getAISBLDirectors() {
+    if (empty($this->aisbl_directors)) {
+      $this->aisbl_directors = $this->_fetchInfo("BRBE");
+    }
+    return $this->aisbl_directors;
+  }
+
+  /**
    * This function fetches a directors bio from a php file
    *
    * @return array
@@ -72,14 +87,14 @@
    *
    * @return array
    * */
-  private function _fetchInfo() {
+  private function _fetchInfo($relation = "BR") {
     $directors = array();
 
     // Members with company relationships
     $sql = "SELECT p.FName, p.LName, o.Name1 as Param, o.OrganizationID
             FROM  People as p, OrganizationContacts as oc, Organizations as o
             WHERE p.PersonID = oc.PersonID
-            AND oc.Relation = 'BR'
+            AND oc.Relation = '". $relation ."'
             AND oc.OrganizationID = o.OrganizationID";
     $result = $this->App->foundation_sql($sql);
 
@@ -87,6 +102,11 @@
       $directors[ucwords($row['LName'] . ', ' . $row['FName'])] = $this->_fetchBioFromFile($row);
     }
 
+    if ($relation != "BR") {
+      ksort($directors);
+      return $directors;
+    }
+
     // Elected add-in provider reps
     $sql = "SELECT p.FName, p.LName, pr.Relation as Relation
             FROM  People as p, PeopleRelations as pr
diff --git a/eclipse.org-common/classes/downloads/DownloadsProject.class.php b/eclipse.org-common/classes/downloads/DownloadsProject.class.php
index d16b56a..d0001af 100644
--- a/eclipse.org-common/classes/downloads/DownloadsProject.class.php
+++ b/eclipse.org-common/classes/downloads/DownloadsProject.class.php
@@ -1,14 +1,18 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2015, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
 
 //if name of the file requested is the same as the current file, the script will exit directly.
 if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
diff --git a/eclipse.org-common/classes/downloads/comparePackages.class.php b/eclipse.org-common/classes/downloads/comparePackages.class.php
new file mode 100644
index 0000000..a26c5ef
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/comparePackages.class.php
@@ -0,0 +1,332 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Christopher Guindon (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) {
+  exit();
+}
+
+require_once (realpath(dirname(__FILE__) . "/../../system/app.class.php"));
+
+/**
+ * Compare packages
+ *
+ * Migrated from downloads.git
+ *
+ * @author chrisguindon
+ */
+class ComparePackages {
+  private $App = NULL;
+  protected $os_display = '';
+  protected $display = '';
+  private $platform = array();
+  private $legend = array();
+  private $devmode = FALSE;
+  private $images = array(
+    0 => '',
+    1 => array(
+      'included',
+      'check.jpg'
+    ),
+    // 2 => array('partially included', 'checkpartial.jpg'),
+    2 => array(
+      'Included (with Source)',
+      'checksource.jpg'
+    )
+  );
+  protected $release = 'photon';
+  private $header = array();
+  private $header_strip = array(
+    '(includes Incubating components)',
+    'Eclipse IDE for ',
+    'Eclipse for ',
+    'Eclipse IDE for ',
+    'Developers',
+    'Software',
+    'Eclipse'
+  );
+  private $row = array();
+  private $path_xml_download = '/home/data/httpd/writable/community/';
+  protected $features_accepted = array();
+  protected $features_list = array();
+  private $path_xml_packages = 'Win.xml';
+  private $prefix_package = '';
+  public $protocol = 'http';
+
+  public function __construct($App = NULL) {
+    if (!is_a($App, 'App')) {
+      $App = new App();
+    }
+    $this->App = $App;
+
+    if (!empty($this->App->devmode) && $this->App->devmode == TRUE) {
+      $this->path_xml_download = $_SERVER['DOCUMENT_ROOT'] . '/downloads-xml/';
+    }
+    $this->protocol = $this->App->getHTTPPrefix();
+    $this->setupPlatform($this->App);
+    $this->features_accepted = $this->getFeaturesXml();
+
+    $this->setPrefixPackage('release');
+    $this->setRelease('latest');
+  }
+
+  public function setRelease($release) {
+    $releases = array(
+      'juno',
+      'kepler',
+      'luna',
+      'mars',
+      'neon',
+      'oxygen',
+      'photon',
+      '2018-09',
+      'latest'
+    );
+    if (in_array($release, $releases)) {
+      $this->release = $release;
+      $this->features_list = $this->getFeaturesList();
+    }
+  }
+
+  public function getLegend() {
+    foreach ($this->images as $id => $i) {
+      $this->legend[] = $this->getLegendImage($id);
+    }
+    return implode(' ', $this->legend);
+  }
+
+  public function setPrefixPackage($prefix) {
+    $this->prefix_package = $prefix . 'Cache';
+    $this->prepareDownloads();
+  }
+
+  function getOs() {
+    return $this->os_display;
+  }
+
+  protected function prepareDownloads() {
+    $od = $this->os_display;
+    if ($od == "linux" || $od == "linux-x64") {
+      $this->display = "Linux";
+      $this->updatePackages($this->prefix_package . "Linux.xml");
+    }
+    elseif ($od == "macosx" || $od == "cocoa64") {
+      $this->display = "macOS";
+      $this->updatePackages($this->prefix_package . "Cocoa.xml");
+    }
+    elseif ($od == "carbon") {
+      $this->display = "macOS";
+      $this->updatePackages($this->prefix_package . "Carbon.xml");
+    }
+    else {
+      $this->display = "Windows";
+      $this->updatePackages($this->prefix_package . "Win.xml");
+    }
+  }
+
+  public function updatePackages($path) {
+    $this->path_xml_packages = $path;
+    $packages = simplexml_load_file($this->path_xml_download . $this->path_xml_packages, NULL, LIBXML_NOCDATA);
+    $this->packages = $this->hackPackages($packages);
+  }
+
+  public function getPackages($package = NULL) {
+    foreach ($this->packages as $p) {
+      if ($p['package_bugzilla_id'] == $package) {
+        return $p;
+      }
+    }
+    return $this->packages;
+  }
+
+  public function getReadableFeature($id = NULL) {
+    if (is_null($id) || $id == "" || empty($this->features_list[$id])) {
+      return FALSE;
+    }
+    $this->features_list[$id]['name'] = (substr($this->features_list[$id]['name'], 0, 8) == 'Eclipse ') ? str_replace('Eclipse ', '', $this->features_list[$id]['name']) : $this->features_list[$id]['name'];
+    if ($this->features_list[$id]['name'] == "%feature.label") {
+      return FALSE;
+    }
+    return $this->features_list[$id];
+  }
+
+  public function output() {
+    $this->getPackageData();
+    ob_start();
+    ?>
+<table id="compareTable" class="table">
+	<thead>
+		<tr>
+      <?php
+    foreach ($this->header as $t) {
+      print $t;
+    }
+    ?>
+    </tr>
+	</thead>
+	<tbody>
+      <?php
+    $count = 0;
+    foreach ($this->row as $t) {
+      $count++;
+      print '<tr id="row-' . $count . '">';
+      foreach ($t as $c) {
+        print $c;
+      }
+      print '</tr>';
+    }
+    ?>
+    </tbody>
+</table>
+<?php
+    return ob_get_clean();
+  }
+
+  private function getFeaturesXml() {
+    // feature restriction
+    $url = simplexml_load_file($this->path_xml_download . 'featuresRestriction.xml');
+    $json = json_encode($url);
+    return json_decode($json, TRUE);
+  }
+
+  private function getFeaturesList() {
+    // readable features
+    $url = $this->path_xml_download . 'features' . ucfirst($this->release) . '.json';
+    $json = json_decode(file_get_contents($url), TRUE);
+    return $this->renameFeatures($json);
+  }
+
+  private function hackPackages($p) {
+
+    // adding RCP to all packages.
+    foreach ($p->package as $f) {
+      $ex = explode(',;', $f->features);
+      if (!in_array('org.eclipse.rcp', $ex)) {
+        $f->features = $f->features . 'org.eclipse.rcp,;';
+      }
+
+      // Scout
+      if ($f['icon'] == 'http://www.eclipse.org/downloads/images/scout.jpg') {
+        $f->features = $f->features . 'org.eclipse.scout.source,;';
+      }
+
+      if ($f['icon'] == 'http://www.eclipse.org/downloads/images/dsl-package.jpg') {
+        $f->features = $f->features . 'org.eclipse.rcp.source,;org.eclipse.cvs.source,;org.eclipse.jdt.source,;org.eclipse.pde.source,;org.eclipse.xtend.sdk.source,;org.eclipse.xtext.sdk.source';
+      }
+      $count = 1;
+      $f['icon'] = str_replace('http://www.eclipse.org', '', $f['icon'], $count);
+      $f['id'] = $f['package_bugzilla_id'];
+      $f['url'] = str_replace('http:', '', $f['url'], $count);
+      $f['downloadurl'] = str_replace('http:', '', $f['downloadurl'], $count);
+      $f['downloadurl64'] = str_replace('http:', '', $f['downloadurl64'], $count);
+    }
+
+    return $p;
+  }
+
+  private function renameFeatures($f) {
+    return $f;
+  }
+
+  private function getPackageData() {
+    $count = 0;
+
+    $this->header[] = '<td class="col-' . $count . '"></td>';
+    $this->row['radio'][] = '<td id="td_info" class="col-' . $count . '"><span>Select packages to compare</span></td>';
+
+    // Setting up the first two rows
+    foreach ($this->packages->package as $p) {
+      $count++;
+      $name = str_replace(' and ', '/', str_replace($this->header_strip, '', $p['name']));
+      $this->row['radio'][] = '<td class="col-' . $count . '"><input type="checkbox" name="controls" id="controls-' . $count . '" value="col-' . $count . '" class="input-radio"/></td>';
+      $this->header[] = '<td class="col-' . $count . '"><a href="' . $this->protocol . '://eclipse.org' . $p['url'] . '" title="' . $p['name'] . '"><img width="32" src="' . $p['icon'] . '"><br/>' . $name . '</a></td>';
+    }
+
+    // creating a row from each feature
+    foreach ($this->features_accepted['item'] as $a) {
+      $count = 0;
+      $multif = explode(';', $a);
+      $rfeatures = $this->getReadableFeature($multif[0]);
+      if (empty($rfeatures)) {
+        continue;
+      }
+      $this->row[$multif[0]][] = '<td class="td_feature-name col-' . $count . '"><span title="' . $rfeatures['description'] . '">' . $rfeatures['name'] . '</span></td>';
+      foreach ($this->packages->package as $p) {
+        $count++;
+        $xfeatures = explode(",;", $p->features);
+        foreach ($multif as $aa) {
+          if (!empty($this->features_list[$aa]['id']) && in_array($this->features_list[$aa]['id'] . '.source', $xfeatures)) {
+            $img = 2;
+            break;
+          }
+          elseif (in_array($aa, $xfeatures)) {
+            $img = 1;
+            break;
+            /*
+             * }elseif ($a == 'org.eclipse.rcp'){
+             * $img = 1;
+             */
+          }
+          else {
+            $img = 0;
+          }
+        }
+        $this->row[$multif[0]][] = '<td class="col-' . $count . '">' . $this->getLegendImage($img) . '</td>';
+      }
+    }
+  }
+
+  private function getLegendImage($id = 0) {
+    if (!$id) {
+      return '&nbsp;';
+    }
+
+    $image_prefix = '/downloads/images/';
+    return '<img width="16" src="' . $image_prefix . $this->images[$id][1] . '" alt="' . $this->images[$id][0] . '"><span class="check-description">' . $this->images[$id][0] . '</span>';
+  }
+
+  public function getRelease() {
+    return $this->release;
+  }
+
+  private function setupPlatform($App) {
+    $this->os_display = (!isset($_GET['osType'])) ? $this->App->getClientOS() : $_GET['osType'];
+    if ($this->os_display == 'linux-x64') {
+      $this->os_display = 'linux';
+    }
+
+    // default to win32 if $this->App->getClientOS() is returning something
+    // strange.
+    $platform = array(
+      'win32',
+      'linux',
+      'macosx'
+    );
+    if (!in_array($this->os_display, $platform)) {
+      $this->os_display = 'win32';
+    }
+
+    $this->platform['win32'] = array(
+      'name' => 'Windows',
+      'shortname' => 'Windows'
+    );
+    $this->platform['linux'] = array(
+      'name' => 'Linux',
+      'shortname' => 'Linux'
+    );
+    $this->platform['macosx'] = array(
+      'name' => 'macOS',
+      'shortname' => 'macOS'
+    );
+  }
+}
diff --git a/eclipse.org-common/classes/downloads/downloadDirectory.class.php b/eclipse.org-common/classes/downloads/downloadDirectory.class.php
new file mode 100644
index 0000000..7450d1b
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/downloadDirectory.class.php
@@ -0,0 +1,415 @@
+<?php
+/**
+ * Copyright (c) 2020 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/app.class.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/session.class.php");
+require_once("/home/data/httpd/eclipse-php-classes/system/ldapconnection.class.php");
+
+class DownloadDirectory {
+
+  /**
+   * App object
+   */
+  private $App;
+
+  /**
+   * Processing paths
+   */
+  private $processing_paths = array();
+
+  /**
+   *
+   * The directory to work with
+   */
+ private $basedir = "";
+
+  /**
+   * Person ID
+   */
+  private $person_id = "";
+
+  /**
+   * LDAP Group
+   */
+  private $ldap_group = NULL;
+
+  /**
+   * User is committer
+   */
+  private $user_is_committer = NULL;
+
+  private $request_uri = "";
+
+  public function __construct() {
+    $this->App = new App();
+
+  }
+
+  /**
+   * Get current path
+   *
+   * @param string $file
+   *
+   * @return string
+   */
+  private function _getPath($file) {
+    if (empty($file)) {
+      return "";
+    }
+
+    $file = $this->App->checkPlain($file);
+    $current_dir_path = $this->_getUri();
+
+    // Remove the last directory from the path
+    $current_dir_path_array = explode('/', $current_dir_path);
+    $count = count($current_dir_path_array);
+    unset($current_dir_path_array[$count - 1]);
+
+    // Scan through the parent's current directory to find out
+    // the proper way to write the current directory.
+    $parent_path = implode('/', $current_dir_path_array);
+    $parent_path = rtrim($parent_path, '/') . "/";
+
+    // Validate if we're dealing with an existing file or directory
+    $file_path = $parent_path . $file;
+    if (is_file($this->getCurrentDirectory() . $file) || is_dir($this->getCurrentDirectory() . $file)) {
+      return $file_path;
+    }
+
+    return "";
+  }
+
+  /**
+   * Get the output HTML of a file
+   *
+   * @return string
+   */
+  private function _getFileOutput($file) {
+
+    if (empty($file)) {
+      return "";
+    }
+
+    $path = $this->_getPath($file);
+    $processing_paths = $this->_getProcessingRequests();
+
+    $input_disabled = '';
+    $suffix_text = '';
+    if (array_key_exists($path, $processing_paths)) {
+      $action = 'archived';
+      if ($this->_isArchiveDomain()) {
+        $action = 'deleted';
+      }
+      $suffix_text = '<span class="small">(This file is being ' . $action . ')</span>';
+
+      # examine the token (return value from the handler
+      if(!empty($processing_paths[$path])) {
+          $suffix_text = '<span class="small">(File cannot be ' . $action . ': ' . $processing_paths[$path] . '. Please contact webmaster.)</span>';
+      }
+      $input_disabled = 'disabled="disabled"';
+    }
+
+    $link = "<img src='//dev.eclipse.org/small_icons/actions/edit-copy.png'><a href='" . $path . "'> " . $file . "</a>";
+    if (empty($path) || !$this->_userIsCommitterOnProject()) {
+      return '<p>'.$link.'</p>';
+    }
+    return '<p><input ' . $input_disabled . ' type="checkbox" name="paths_to_archive[]" value="'. $path .'"> - ' . $link . ' ' . $suffix_text . '</p>';
+  }
+
+  /**
+   * Get the output HTML of a folder
+   *
+   * @return string
+   */
+  private function _getFolderOutput($directory) {
+
+    if($directory === ".") {
+      return "";
+    }
+
+    $path = $this->_getPath($directory);
+    $processing_paths = $this->_getProcessingRequests();
+
+    $input_disabled = '';
+    $suffix_text = '';
+    if (array_key_exists($path, $processing_paths)) {
+      $action = 'archived';
+      if ($this->_isArchiveDomain()) {
+        $action = 'deleted';
+      }
+      $suffix_text = '<span class="small">(This folder is being ' . $action . ')</span>';
+
+      # examine the token (return value from the handler
+      if(!empty($processing_paths[$path])) {
+        $suffix_text = '<span class="small">(Folder cannot be ' . $action . ': ' . $processing_paths[$path] . '. Please contact webmaster.)</span>';
+      }
+      $input_disabled = 'disabled="disabled"';
+    }
+
+    $link = "<img src='//dev.eclipse.org/small_icons/places/folder.png'><a href='" . $path . "'> " . $directory . "</a> " . $suffix_text;
+
+    if (empty($path) || $directory === ".." || !$this->_userIsCommitterOnProject()) {
+      return '<p>'.$link.'</p>';
+    }
+
+    return '<p><input ' . $input_disabled . ' type="checkbox" name="paths_to_archive[]" value="'. $path .'"> - ' . $link . '</p>';
+  }
+
+  /**
+   * Get Person ID from Session
+   *
+   * @return string
+   */
+  private function _getPersonID() {
+    if (empty($this->person_id)) {
+      $Session = new Session();
+      $Friend = $Session->getFriend();
+      $this->person_id = $Friend->getUID();
+    }
+    return $this->person_id;
+  }
+
+  /**
+   * Get all the processing requests from account_requests table
+   *
+   * @return array
+   */
+  private function _getProcessingRequests() {
+
+    if (!empty($this->processing_paths)) {
+      return $this->processing_paths;
+    }
+
+    $action = "DOWNLOAD_ARCHIVE";
+    if ($this->_isArchiveDomain()) {
+      $action = "DOWNLOAD_DELETE";
+    }
+
+    $sql = "SELECT password as Path, token
+      FROM account_requests
+      WHERE fname = " . $this->App->returnQuotedString($this->App->sqlSanitize($action)) . "
+      AND lname = " . $this->App->returnQuotedString($this->App->sqlSanitize($action));
+    $result = $this->App->eclipse_sql($sql);
+
+    if (empty($result)) {
+      $this->processing_paths;
+    }
+
+    while($myrow = mysql_fetch_array($result)) {
+      $this->processing_paths[$myrow['Path']] = $myrow['token'];
+    }
+    return $this->processing_paths;
+  }
+
+  /**
+   * Get uri
+   *
+   * @return string
+   */
+  private function _getUri() {
+    if (empty($this->request_uri)) {
+      $this->request_uri = $_SERVER['REQUEST_URI'];
+    }
+    return str_replace("?d", "", $this->request_uri);
+  }
+
+  /**
+   * Get the url of the current directory
+   *
+   * @return string
+   */
+  public function getCurrentDirectory() {
+    return $_SERVER['DOCUMENT_ROOT'] . urldecode($this->_getUri());
+  }
+
+  /**
+   * Get the project ID based on the group owner of the folder
+   *
+   * @return string
+   */
+  private function _getProjectID() {
+    $group = $this->getLdapGroupByGid(filegroup($this->basedir));
+
+    if (empty($group)) {
+      return "";
+    }
+    return $group;
+  }
+
+  /**
+   * Insert into account_requests table
+   *
+   * @return bool
+   */
+  private function _insertRequest() {
+    if (empty($_POST['paths_to_archive'])) {
+      return FALSE;
+    }
+
+    $action = "DOWNLOAD_ARCHIVE";
+    if ($this->_isArchiveDomain()) {
+      $action = "DOWNLOAD_DELETE";
+    }
+
+    foreach ($_POST['paths_to_archive'] as $path) {
+      $sql = "SELECT
+              email
+              FROM account_requests
+              WHERE email = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->_getPersonID())) . "
+              AND password = ". $this->App->returnQuotedString($this->App->sqlSanitize($path));
+      $result = $this->App->eclipse_sql($sql);
+      while ($row = mysql_fetch_array($result)) {
+        if (!empty($row['email'])) {
+          return FALSE;
+        }
+      }
+
+      $sql = "INSERT INTO account_requests (
+          email,
+          new_email,
+          fname,
+          lname,
+          password,
+          ip,
+          req_when,
+          token
+        )
+          VALUES (
+          " . $this->App->returnQuotedString($this->App->sqlSanitize($this->_getPersonID())) . ",
+          NULL,
+          " . $this->App->returnQuotedString($this->App->sqlSanitize($action)) . ",
+          " . $this->App->returnQuotedString($this->App->sqlSanitize($action)) . ",
+          " . $this->App->returnQuotedString($this->App->sqlSanitize($path)) . ",
+          " . $this->App->returnQuotedString($this->App->sqlSanitize($this->App->getRemoteIPAddress())) . ",
+          NOW(),
+          NULL
+          )";
+      $this->App->eclipse_sql($sql);
+    }
+  }
+
+  /**
+   * Check if the current domain is archive.eclipse.org
+   *
+   * @return bool
+   */
+  private function _isArchiveDomain() {
+    if (!empty($_SERVER['HTTP_HOST']) && strpos($_SERVER['HTTP_HOST'], 'archive.eclipse.org') !== FALSE) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Check if the user is a committer on a specific project
+   *
+   * @return bool
+   */
+  private function _userIsCommitterOnProject() {
+
+    if (!is_null($this->user_is_committer)) {
+      return $this->user_is_committer;
+    }
+
+    $sql = "SELECT count(1) as count
+      FROM PeopleProjects
+      WHERE PersonID = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->_getPersonID())) . "
+      AND ProjectID = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->_getProjectID())) . "
+      AND Relation = " . $this->App->returnQuotedString("CM") . "
+      AND (InactiveDate IS NULL OR InactiveDate = '0000-00-00')";
+    $result = $this->App->foundation_sql($sql);
+    $this->user_is_committer = FALSE;
+    while($myrow = mysql_fetch_array($result)) {
+      if ($myrow['count']) {
+        $this->user_is_committer = TRUE;
+      }
+    }
+
+    return $this->user_is_committer;
+  }
+
+
+
+  /**
+   * Get the Form ouput
+   *
+   * @return string
+   */
+  public function getFormOutput($files, $dirs, $basedir=null) {
+
+    if($basedir === null) {
+      $basedir = $this->getCurrentDirectory();
+    }
+    $this->basedir = $basedir;
+
+    $output = "";
+    $html_checkboxes = array();
+    foreach ($dirs as $directory) {
+      if($directory === ".") {
+        continue;
+      }
+
+      if ($directory === ".." || $this->_userIsCommitterOnProject() === FALSE) {
+        $output .= $this->_getFolderOutput($directory);
+        continue;
+      }
+
+      $html_checkboxes[] = $this->_getFolderOutput($directory);
+    }
+
+    foreach ($files as $file) {
+      if ($this->_userIsCommitterOnProject() === FALSE) {
+        $output .= $this->_getFileOutput($file);
+      }
+      $html_checkboxes[] = $this->_getFileOutput($file);
+    }
+
+    if ($this->_userIsCommitterOnProject() === FALSE) {
+      return $output;
+    }
+
+    // Now that we know that the current user is a committer for this project,
+    // we can safely insert a new request on page reload
+    $this->_insertRequest();
+
+    $output .= '<form class="downloads-directory" method="post" action="/errors/filehandler.php">';
+    $output .= implode("", $html_checkboxes);
+
+    $button_text = 'Move to archive.eclipse.org';
+    $button_class = 'btn-primary';
+    if ($this->_isArchiveDomain()) {
+      $button_text = 'Delete';
+      $button_class = 'btn-danger';
+    }
+
+    $output .= '<input disabled id="deletesubmit" class="btn btn-xs ' . $button_class . '" type="submit" value="' . $button_text . '" />';
+    $output .= "</form>";
+    $output .= "<span class='small'>File and folder operations make take several seconds to complete. Refresh the page to get current status.</span>";
+    return $output;
+  }
+
+  /**
+   * Get the LDAP Group name, by gid
+   *
+   * @return string
+   */
+  public function getLdapGroupByGid($gid) {
+    if (!is_null($this->ldap_group)) {
+      return $this->ldap_group;
+    }
+    $LDAPConnection = new LDAPConnection();
+    $this->ldap_group = $LDAPConnection->getGroupByGid($gid);
+    return $this->ldap_group;
+  }
+}
diff --git a/eclipse.org-common/classes/downloads/downloads.class.php b/eclipse.org-common/classes/downloads/downloads.class.php
index f8318aa..c995af0 100644
--- a/eclipse.org-common/classes/downloads/downloads.class.php
+++ b/eclipse.org-common/classes/downloads/downloads.class.php
@@ -1,23 +1,26 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
+ * Eric Poirier (Eclipse Foundation) - initial API and implementation
+ * Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 //if name of the file requested is the same as the current file, the script will exit directly.
 if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
 
-require_once(dirname(__FILE__) . "/DownloadsProject.class.php");
-require_once($_SERVER['DOCUMENT_ROOT'] . "/membership/promo/promos.php");
-require_once(dirname(__FILE__) . "/eclipseInstaller.php");
-require_once(dirname(__FILE__) . "/../ads/promotedDownloads.class.php");
-require_once(dirname(__FILE__) . "/../ads/downloadsBannerAd.class.php");
+require_once("DownloadsProject.class.php");
+require_once("eclipseInstaller.php");
+require_once("promotedDownloads.class.php");
+require_once(realpath(dirname(__FILE__) . "/../ads/promotions.class.php"));
+require_once(realpath(dirname(__FILE__) . "/../ads/downloadsBannerAd.class.php"));
 
 class Downloads extends DownloadsProject {
 
@@ -37,7 +40,7 @@
 
   public function __construct() {
 
-    $this->Installer = new EclipseInstaller('oxygen/R2');
+    $this->Installer = new EclipseInstaller();
     $this->Installer->setInstallerLayout('layout_a');
 
     $this->PromotedDownloads = New PromotedDownloads();
@@ -71,13 +74,24 @@
 
     // Runtime Platforms item
     $Project = new DownloadsProject();
+    $Project->setTitle('GlassFish');
+    $Project->setDescription('Eclipse GlassFish provides a complete application server which serves as a compatible implementation for the Jakarta EE specification.');
+    $Project->setLogo('assets/public/images/logo-glassfish.png');
+    $Project->setProjectType($this->projects['runtime_platforms']['title']);
+    $Project->setDownloadUrl64Bit('https://projects.eclipse.org/projects/ee4j.glassfish/downloads');
+    $Project->setLearnMoreUrl('https://projects.eclipse.org/projects/ee4j.glassfish');
+    $Project->setProjectsAttributes('image','height','75');
+    $this->newProject($Project);
+
+    // Runtime Platforms item
+    $Project = new DownloadsProject();
     $Project->setTitle('Jetty');
     $Project->setDescription('Eclipse Jetty provides a web server and javax.servlet container.');
     $Project->setLogo('assets/public/images/logo-jetty.png');
     $Project->setProjectType($this->projects['runtime_platforms']['title']);
     $Project->setDownloadUrl64Bit('https://www.eclipse.org/jetty/download.html');
     $Project->setLearnMoreUrl('http://www.eclipse.org/jetty/');
-    $Project->setProjectsAttributes('container','class','jetty-spacing');
+    $Project->setProjectsAttributes('container','class');
     $this->newProject($Project);
 
     // Runtime Platforms item
@@ -86,7 +100,7 @@
     $Project->setDescription('Eclipse Equinox is an implementation of the OSGi core framework specification.');
     $Project->setLogo('assets/public/images/logo-equinox.png');
     $Project->setProjectType($this->projects['runtime_platforms']['title']);
-    $Project->setDownloadUrl64Bit('http://projects.eclipse.org/projects/rt.equinox/downloads');
+    $Project->setDownloadUrl64Bit('http://download.eclipse.org/equinox/');
     $Project->setLearnMoreUrl('http://www.eclipse.org/equinox/');
     $Project->setProjectsAttributes('image','height','50');
     $this->newProject($Project);
@@ -220,8 +234,7 @@
    * @return string
    */
   public function getPromoAd() {
-    $adNo = (isset($_GET['adNo'])) ? $_GET['adNo'] : '';
-    $promo = chooseDownloadAd($adNo);
+    $promo = Promotions::output();
     return $promo;
   }
 
@@ -235,7 +248,7 @@
   private function _projectsOutput($projects) {
     ob_start();
     foreach ($projects as $project) {
-      include 'tpl/downloadsProjects.tpl.php';
+      include 'views/view.projects.php';
     }
     return ob_get_clean();
   }
@@ -248,7 +261,7 @@
   public function getAllDownloadsProjects() {
     ob_start();
     foreach ($this->projects as $key =>$category) {
-      include 'tpl/downloadsCategory.tpl.php';
+      include 'views/view.category.php';
     }
     return ob_get_clean();
   }
diff --git a/eclipse.org-common/classes/downloads/eclipseInstaller.php b/eclipse.org-common/classes/downloads/eclipseInstaller.php
index 49ba97b..f4c49cd 100644
--- a/eclipse.org-common/classes/downloads/eclipseInstaller.php
+++ b/eclipse.org-common/classes/downloads/eclipseInstaller.php
@@ -1,20 +1,22 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2015, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *    Eric Poirier (Eclipse Foundation)
- *******************************************************************************/
+ *   Christopher Guindon (Eclipse Foundation)  - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 
 //if name of the file requested is the same as the current file, the script will exit directly.
 if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
 
-require_once(dirname(__FILE__) . "/../../system/eclipseenv.class.php");
+require_once(realpath(dirname(__FILE__) . "/../../system/eclipseenv.class.php"));
 
 class EclipseInstaller extends EclipseEnv {
 
@@ -28,24 +30,35 @@
 
   private $download_links = array();
 
+  private $allow_toggle = TRUE;
+
+  private $release_title = "";
+
   /**
    * Constructor
    */
-  function __construct($release = NULL) {
+  function __construct($release = 'latest') {
     parent::__construct();
-    $this->_addPlaform('Mac OS X');
+    $this->_addPlaform('macOS');
     $this->_addPlaform('Windows');
     $this->_addPlaform('Linux');
 
-    if (!is_null($release)) {
-      // Let's load the json feed to get the links for this release.
-      $this->_loadJson($release);
+    // Let's load the json feed to get the links for this release.
+    $this->_loadJson($release);
+    // Build the array containing all the download links
+    $this->setDownloadLinks();
 
-      // Build the array containing all the download links
-      $this->setDownloadLinks();
+  }
+
+  public function setAllowToggle($bool = TRUE) {
+    if (is_bool($bool)) {
+      $this->allow_toggle = $bool;
     }
   }
 
+  public function getAllowToggle() {
+    return $this->allow_toggle;
+  }
   /**
    * Add a link to the Eclipse Installer
    *
@@ -54,7 +67,7 @@
    * @param string $text
    * @return boolean
    */
-  public function addlink($platform = '', $url = '', $text = '') {
+  public function addlink($platform = '', $url = '', $text = '', $jre = FALSE) {
 
     if(!isset($this->platform[$this->_removeSpaces($platform)])) {
       return FALSE;
@@ -64,10 +77,11 @@
     $platform_array = array(
       'platform' => $platform,
       'count' =>$count,
-      'link_classes' => "btn btn-warning",
+      'link_classes' => "btn btn-warning margin-bottom-5",
       'url' => $url,
       'text' => $text,
       'text_prefix' => 'Download',
+      'jre' => $jre
     );
 
     $this->setPlatform($platform_array);
@@ -88,16 +102,20 @@
       $os_client = $os;
     }
 
-    $installer_links = $this->getInstallerArray($version, $os_client);
-
     if (!empty($layout)) {
+      $installer_alert_text = $this->getInstallerAlertText();
       switch ($layout) {
         case 'layout_a':
-          $tpl = "view/eclipseInstallerLayoutA.php";
+          $release_title = $this->getReleaseShortName(TRUE);
+          $installer_links = $this->getInstallerArray($version, $os_client);
+          $tpl = "views/view.installer-a.php";
           break;
         case 'layout_b':
+          $release_title = $this->getReleaseShortName(TRUE) . '&nbsp;' . $this->getReleaseType();
+          $release_title_default = $this->getReleaseShortName() . ' ' . $this->getReleaseType();
           $download_count = $this->total_download_count;
-          $tpl = "view/eclipseInstallerLayoutB.php";
+          $installer_links = $this->getInstallerArray();
+          $tpl = "views/view.installer-b.php";
           break;
       }
       ob_start();
@@ -108,6 +126,36 @@
   }
 
   /**
+   * Return the installer alert text
+   *
+   * @return string
+   */
+  function getInstallerAlertText() {
+    $release_name = $this->getReleaseShortName(TRUE) . " " . $this->getReleaseType();
+
+    $download_links = $this->getDownloadLinks();
+
+    $platforms = array();
+    foreach ($download_links as $platform) {
+      foreach ($platform['links'] as $link) {
+
+        if ($link['jre'] === TRUE) {
+          $platforms[] = str_replace(' ', '&nbsp;', $link['platform']);
+        }
+      }
+    }
+
+    if (empty($platforms)) {
+      return "";
+    }
+
+    $string_platforms = implode(', ', $platforms);
+    $string_platforms = substr_replace($string_platforms, ' and', strrpos($string_platforms, ','), 1);
+
+    return "The Eclipse Installer " . $release_name . " now includes a JRE for " . $string_platforms . ".";
+  }
+
+  /**
    * Returns the layout for the Installer
    *
    * @return string
@@ -146,6 +194,63 @@
   }
 
   /**
+   * Set the release title
+   *
+   * @param string $title
+   */
+  public function setReleaseTitle($title) {
+    if (!empty($title)) {
+      $this->release_title = $title;
+    }
+  }
+
+  /**
+   * Get the release title
+   *
+   * @return string
+   */
+  public function getReleaseTitle() {
+    return $this->release_title;
+  }
+
+  /**
+   * Get the release short name
+   *
+   * @param bool $non_breaking_string
+   *
+   * @return string
+   */
+  public function getReleaseShortName($non_breaking_string = FALSE) {
+
+    if ($release_title = $this->getReleaseTitle()) {
+      $release_title = explode('/', $release_title);
+      $short_name = $release_title[0];
+
+      if ($non_breaking_string) {
+        $short_name = str_replace('-', '&#8209;', $short_name);
+      }
+      return $short_name;
+    }
+
+    return "";
+  }
+
+  /**
+   * Get the release type
+   *
+   * @return string
+   */
+  public function getReleaseType() {
+
+    if ($release_title = $this->getReleaseTitle()) {
+      $release_title = explode('/', $release_title);
+      return $release_title[1];
+    }
+
+    return "";
+  }
+
+  /**
    * Return a platform
    *
    * @return array
@@ -175,7 +280,7 @@
   public function getInstallerLinks($version = NULL, $os = NULL) {
 
     $os_client = $this->_getClientOS();
-    $accepted_os = array('windows','macosx','linux');
+    $accepted_os = array('windows','macos','linux');
     if (!empty($os) && in_array($os, $accepted_os)) {
       $os_client = $os;
     }
@@ -193,6 +298,19 @@
     return $links;
   }
 
+  public function getInstallerInstructions(){
+    $class = 'collapse';
+    if (!$this->getAllowToggle()) {
+      $class .= ' in';
+    }
+    $html = '<div id="collapseEinstaller1">';
+    $html .= '<div class="' . $class . '" id="collapseEinstaller">';
+    $html .= '<div class="well">';
+    ob_start();
+    include('views/view.installer-instructions.php');
+    return $html . ob_get_clean() . '</div></div></div>';
+  }
+
   /**
    * Returns the appropriate array based on the Version and OS if specified
    *
@@ -211,12 +329,12 @@
       return $download_links;
     }
 
-   $accepted_version = array('64bit','32bit');
+   $accepted_version = array('x86_64','32bit', 'AArch64');
     if (!empty($version) && !in_array($version, $accepted_version)) {
       return array();
     }
 
-    $accepted_os = array('windows','macosx','linux');
+    $accepted_os = array('windows','macos','linux');
     if (!empty($os) && !in_array($os, $accepted_os)) {
       return array();
     }
@@ -260,23 +378,27 @@
     $eclipse_env = $this->getEclipseEnv();
 
     if (!empty($data['files']['mac64'])) {
-      $this->addlink('Mac OS X', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['mac64']['url']), "64 bit");
+      $this->addlink('macOS', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['mac64']['url']), "x86_64", $data['files']['mac64']['jre']);
     }
 
     if (!empty($data['files']['win32'])) {
-      $this->addlink('Windows', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['win32']['url']), '32 bit');
+      $this->addlink('Windows', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['win32']['url']), '32 bit', $data['files']['win32']['jre']);
     }
 
     if (!empty($data['files']['win64'])) {
-      $this->addlink('Windows', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['win64']['url']), '64 bit');
+      $this->addlink('Windows', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['win64']['url']), 'x86_64', $data['files']['win64']['jre']);
     }
 
     if (!empty($data['files']['linux32'])) {
-      $this->addlink('Linux', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['linux32']['url']), '32 bit');
+      $this->addlink('Linux', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['linux32']['url']), '32 bit', $data['files']['linux32']['jre']);
     }
 
     if (!empty($data['files']['linux64'])) {
-      $this->addlink('Linux', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['linux64']['url']), "64 bit");
+      $this->addlink('Linux', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['linux64']['url']), "x86_64", $data['files']['linux64']['jre']);
+    }
+
+    if (!empty($data['files']['linuxaarch64'])) {
+      $this->addlink('Linux', str_replace('www.eclipse.org', $eclipse_env['domain'], $data['files']['linuxaarch64']['url']), "AArch64", $data['files']['linuxaarch64']['jre']);
     }
   }
 
@@ -309,7 +431,7 @@
       $os = "linux";
     }
     if ($client_os == "macosx" || $client_os == "cocoa64" || $client_os == "carbon") {
-      $os = "macosx";
+      $os = "macos";
     }
 
     // Check if the OS has been selected manually
@@ -334,21 +456,31 @@
 
   /**
    * Load jSON data from file.
+   *
    * @param unknown $release
    */
   private function _loadJson($release) {
     $url = '/home/data/httpd/writable/community/eclipse_installer.json';
-    $json_data =  json_decode(file_get_contents($url), TRUE);
+    $json_data = json_decode(file_get_contents($url), TRUE);
+    $installer = array();
     foreach ($json_data as $data) {
-      if (strtolower($data['release_title']) == strtolower($release)) {
-        $this->json_data = $data;
-        $this->_addLinksFromJson();
-        if (!empty($this->json_data['total_download_count'])) {
-          $this->total_download_count = $this->json_data['total_download_count'];
-        }
+      if ((strtolower($data['release_title']) == strtolower($release)) || ($release === 'latest' && $data['latest_release'] === TRUE)) {
+        $installer = $data;
         break;
       }
     }
+    if (empty($installer) && !empty($json_data[0])) {
+      $installer = $json_data[0];
+    }
+    if (!empty($installer)) {
+      $this->json_data = $installer;
+      $this->_addLinksFromJson();
+      if (!empty($this->json_data['total_download_count'])) {
+        $this->total_download_count = $this->json_data['total_download_count'];
+      }
+      if (!empty($this->json_data['release_title'])) {
+        $this->setReleaseTitle($this->json_data['release_title']);
+      }
+    }
   }
-
 }
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/images/logo-eclipse.png b/eclipse.org-common/classes/downloads/images/logo-eclipse.png
new file mode 100644
index 0000000..05ecb35
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/images/logo-eclipse.png
Binary files differ
diff --git a/eclipse.org-common/classes/downloads/promotedDownloads.class.php b/eclipse.org-common/classes/downloads/promotedDownloads.class.php
new file mode 100644
index 0000000..96f8de1
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/promotedDownloads.class.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Christopher Guindon (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+require_once(realpath(dirname(__FILE__) . "/../ads/eclipseAds.class.php"));
+
+/**
+ * Promoted Downloads (Packages)
+ *
+ * @author chrisguindon
+ */
+class PromotedDownloads extends EclipseAds {
+
+  public function __construct($source = "") {
+    parent::__construct($source);
+
+    // Note: 1 slot = 20
+    // Total = 100
+
+    // EMPTY
+    $Ad = new Ad();
+    $Ad->setTitle('EMPTY');
+    $Ad->setBody("EMPTY");
+    $Ad->setImage("EMPTY");
+    $Ad->setCampaign('EMPTY');
+    $Ad->setUrl("https://");
+    $Ad->setWeight(80);
+    $Ad->setType('empty');
+    $this->newAd($Ad);
+
+  }
+
+  /**
+   * Custom implementation of _build()
+   * @see EclipseAds::_build()
+   *
+   * @param $type - This variable determines help to determine which template file to use
+   */
+  protected function _build($layout = "", $type = "", $impression_id = "") {
+    ob_start();
+    // Layout A is default
+    $tpl = "views/view.promotedDownloads.layout-a.tpl.php";
+    // if Layout B is specified
+    if ($layout == 'layout_b'){
+      $tpl = "views/view.promotedDownloads.layout-b.tpl.php";
+    }
+
+    include($tpl);
+    $this->output = ob_get_clean();
+  }
+}
+
diff --git a/eclipse.org-common/classes/downloads/tpl/downloadsCategory.tpl.php b/eclipse.org-common/classes/downloads/tpl/downloadsCategory.tpl.php
deleted file mode 100644
index cc0334b..0000000
--- a/eclipse.org-common/classes/downloads/tpl/downloadsCategory.tpl.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-?>
-
-<!-- RUNTIMES PLATFORM -->
-<div id="<?php print strtolower(str_replace(" ", "-", $category['title'])); ?>" class="downloads-section">
-  <div class="container">
-    <h2><span class="downloads-title"><?php print $category['title']; ?></span></h2>
-    <div class="row downloads-content-padding">
-
-      <?php if ($key == 'tool_platforms') :?>
-        <!-- Installer -->
-        <div class="col-md-10th col-sm-24">
-          <?php print $this->Installer->output('64bit'); ?>
-        </div>
-      <?php endif;?>
-
-      <?php print $this->getProjectsList($key); ?>
-
-      <?php if ($key == 'tool_platforms') :?>
-        <!-- PROMOTED DOWNLOAD -->
-        <div class="col-md-5th col-sm-8 col-xs-16 col-xs-offset-4 col-sm-offset-0 downloads-items downloads-promoted">
-          <?php print $this->PromotedDownloads->output('layout_a'); ?>
-        </div>
-      <?php endif;?>
-
-    </div>
-  </div>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutA.php b/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutA.php
deleted file mode 100644
index 4819ea0..0000000
--- a/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutA.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation)- initial API and implementation
- *******************************************************************************/
-//if name of the file requested is the same as the current file, the script will exit directly.
-if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<div class="downloads-installer">
-  <span class="downloads-logo vertical-align"><img height="50" alt="Eclipse" src="assets/public/images/logo-eclipse.png"></span>
-  <h3>Get Eclipse <span class="oxygen">Oxygen</span></h3>
-  <p>Install your favorite Eclipse packages.</p>
-  <p>
-    <?php foreach ($installer_links['links'] as $link): ?>
-      <a class="<?php print $link['link_classes']; ?>" href="<?php print $link['url']; ?>" title="<?php print $link['text']; ?> Download"><?php print $link['text_prefix'] . ' ' . $link['text']; ?></a>
-    <?php endforeach; ?>
-  </p>
-  <p><a href="/downloads/eclipse-packages" class="grey-link">Download Packages</a> | <a class="grey-link" href="/downloads/eclipse-packages/?show_instructions=TRUE#page-download" title="Instructions">Need Help?</a></p>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutB.php b/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutB.php
deleted file mode 100644
index 7e9665c..0000000
--- a/eclipse.org-common/classes/downloads/view/eclipseInstallerLayoutB.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015, 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation)- initial API and implementation
- *******************************************************************************/
-//if name of the file requested is the same as the current file, the script will exit directly.
-if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-<div class="installer">
-  <div class="row row-eq-height">
-    <div class="col-md-16 col-sm-14 col-xs-12">
-      <div class="content">
-        <h2>Try the Eclipse <span class="orange">Installer</span></h2>
-        <p>The easiest way to install and update your Eclipse Development Environment.</p>
-        <ul class="list-inline">
-          <li>
-            <a data-target="#collapseEinstaller" class="solstice-collapse orange" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="collapseEinstaller">
-            Find out more
-            </a>
-          </li>
-          <li>
-            <?php if (!empty($download_count)) :?>
-              <strong><i class="fa fa-download"></i> <?php print number_format($download_count);?> Downloads</strong>
-            <?php endif;?>
-          </li>
-        </ul>
-      </div>
-    </div>
-    <div class="col-sm-6 options">
-      <ul class="list-unstyled">
-        <li><i class="fa fa-download white"></i></li>
-        <li class="title"><?php print $installer_links['links'][0]['platform']; ?></li>
-        <li>
-          <ul class="list-inline links">
-            <?php foreach ($installer_links['links'] as $link): ?>
-              <li class="download-link-<?php print $link['count']; ?>">
-                <a href="<?php print $link['url']; ?>" title="<?php print $link['text']; ?> Download"><?php print $link['text']; ?></a>
-              </li>
-            <?php endforeach; ?>
-          </ul>
-        </li>
-      </ul>
-    </div>
-  </div>
-</div>
-
-<div id="collapseEinstaller1">
-  <div class="collapse<?php if (isset($_GET['show_instructions'])) { print ' in';}?>" id="collapseEinstaller">
-    <div class="well">
-      <?php include('eclipseInstaller_instructions.php');?>
-    </div>
-  </div>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/views/view.category.php b/eclipse.org-common/classes/downloads/views/view.category.php
new file mode 100644
index 0000000..6dc2002
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/views/view.category.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+?>
+<!-- RUNTIMES PLATFORM -->
+<div id="<?php print strtolower(str_replace(" ", "-", $category['title'])); ?>" class="downloads-section">
+  <div class="container">
+    <h2><span class="downloads-title"><?php print $category['title']; ?></span></h2>
+    <div class="row downloads-content-padding">
+
+      <?php if ($key == 'tool_platforms') :?>
+        <!-- Installer -->
+        <div class="col-md-10th col-sm-24">
+          <div class="downloads-installer">
+            <?php print $this->Installer->output('x86_64'); ?>
+          </div>
+        </div>
+      <?php endif;?>
+
+      <?php print $this->getProjectsList($key); ?>
+
+      <?php if ($key == 'tool_platforms') :?>
+        <!-- PROMOTED DOWNLOAD -->
+        <div class="col-md-5th col-sm-8 col-xs-16 col-xs-offset-4 col-sm-offset-0 downloads-items downloads-promoted">
+          <?php print $this->PromotedDownloads->output('layout_a'); ?>
+        </div>
+      <?php endif;?>
+
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/views/view.installer-a.php b/eclipse.org-common/classes/downloads/views/view.installer-a.php
new file mode 100644
index 0000000..a6bc0c6
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/views/view.installer-a.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Christopher Guindon (Eclipse Foundation)  - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+//if name of the file requested is the same as the current file, the script will exit directly.
+if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
+?>
+
+<div class="text-center">
+  <?php if (!empty($installer_alert_text)): ?>
+    <div class="row">
+      <div class="col-xs-12 col-xs-offset-6 col-md-18 col-md-offset-3">
+        <div class="downloads-eclipse-installer-alert">
+          <p><?php print $installer_alert_text; ?></p>
+        </div>
+      </div>
+    </div>
+  <?php endif; ?>
+  <span class="downloads-logo vertical-align"><img height="50" alt="Eclipse" src="/downloads/assets/public/images/logo-eclipse.png"></span>
+  <h3>Get <strong>Eclipse IDE <?php print $release_title; ?></strong></h3>
+  <p>Install your favorite desktop IDE packages.</p>
+  <p>
+    <?php foreach ($installer_links['links'] as $link): ?>
+      <a class="<?php print $link['link_classes']; ?>" href="<?php print $link['url']; ?>" title="<?php print $link['text']; ?> Download"><?php print $link['text_prefix'] . ' ' . $link['text']; ?></a>
+    <?php endforeach; ?>
+  </p>
+  <p><a href="/downloads/packages" class="grey-link">Download Packages</a> | <a class="grey-link" href="/downloads/packages/installer" title="Instructions">Need Help?</a></p>
+</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/views/view.installer-b.php b/eclipse.org-common/classes/downloads/views/view.installer-b.php
new file mode 100644
index 0000000..0e593fe
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/views/view.installer-b.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Christopher Guindon (Eclipse Foundation)  - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+//if name of the file requested is the same as the current file, the script will exit directly.
+if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
+?>
+<?php if (!empty($installer_alert_text)): ?>
+  <div class="eclipse-installer-alert">
+    <div class="row">
+      <div class="col-sm-24">
+        <p><?php print $installer_alert_text; ?></p>
+      </div>
+    </div>
+  </div>
+<?php endif; ?>
+
+<div class="eclipse-installer content">
+  <div class="row">
+    <div class="col-md-16">
+      <h2>Try the Eclipse <strong>Installer <small class="white"><?php print $release_title; ?></small></strong></h2>
+      <p>The easiest way to install and update your Eclipse Development Environment.</p>
+      <ul class="list-unstyled margin-bottom-0">
+        <?php if ($this->getAllowToggle()) :?>
+        <li>
+          <a data-target="#collapseEinstaller" class="solstice-collapse orange" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="collapseEinstaller">
+          Find out more
+          </a>
+        </li>
+        <?php endif;?>
+        <li>
+          <?php if (!empty($download_count)) :?>
+            <strong><i class="fa fa-download"></i> <?php print number_format($download_count);?> Installer Downloads</strong>
+          <?php endif;?>
+        </li>
+        <li class="package-download-count" release-title="<?php print $release_title_default; ?>"></li>
+      </ul>
+    </div>
+    <div class="col-md-8 eclipse-installer-download-col">
+      <p class="margin-top-10"><strong>Download</strong></p>
+      <ul class="list-unstyled eclipse-installer-download-links">
+        <?php foreach ($installer_links as $platform => $links):?>
+          <?php
+            print '<li>' . $links['label'] . ' ';
+            $bar = FALSE;
+            foreach ($links['links'] as $link) {
+              print ($bar) ? ' | ' : '';
+              print '<a href="' . $link['url'] . '" title="' . $link['text'] . ' Download" class="">' . $link['text'] . '</a>';
+              $bar = TRUE;
+            }
+            print '</li>';
+          ?>
+        <?php endforeach;?>
+      </ul>
+    </div>
+  </div>
+</div>
+<?php print $this->getInstallerInstructions();?>
diff --git a/eclipse.org-common/classes/downloads/view/eclipseInstaller_instructions.php b/eclipse.org-common/classes/downloads/views/view.installer-instructions.php
similarity index 74%
rename from eclipse.org-common/classes/downloads/view/eclipseInstaller_instructions.php
rename to eclipse.org-common/classes/downloads/views/view.installer-instructions.php
index cdc7f5c..6000a04 100644
--- a/eclipse.org-common/classes/downloads/view/eclipseInstaller_instructions.php
+++ b/eclipse.org-common/classes/downloads/views/view.installer-instructions.php
@@ -1,21 +1,26 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2015,2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation) - Initial implementation
- *    Christopher Guindon (Eclipse Foundation)
- *******************************************************************************/
+ *   Christopher Guindon (Eclipse Foundation)  - initial API and implementation
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 ?>
-<p class="float-right padding-top-25">
-  <a class="btn btn-warning btn-sm" data-target="#collapseEinstaller" class="solstice-collapse orange" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="collapseEinstaller">
-    <i class="fa fa-times"></i> Hide
-  </a>
-</p>
+
+<?php if ($this->getAllowToggle()) :?>
+  <p class="float-right padding-top-25">
+    <a class="btn btn-warning btn-sm" data-target="#collapseEinstaller" class="solstice-collapse orange" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="collapseEinstaller">
+      <i class="fa fa-times"></i> Hide
+    </a>
+  </p>
+<?php endif;?>
 <h1>5 Steps to Install Eclipse</h1>
 
 <p class="lead">
@@ -23,7 +28,7 @@
 to install Eclipse. It is a proper installer (no zip files), with a
 self-extracting download that leads you through the installation process. For
 those who prefer not to use the Installer, the packages and zip files are still
-available on our <a href="/downloads/eclipse-packages/">package download</a> page.</p>
+available on our <a href="/downloads/packages/">package download</a> page.</p>
 <hr>
 <h2>1. Download the Eclipse Installer</h2>
 <?php if (!empty($platforms)) :?>
@@ -39,7 +44,7 @@
   <?php endforeach;?>
   </div>
 <?php else:?>
-  <p>Download Eclipse Installer from <a href="/downloads">http://www.eclipse.org/downloads</a></p>
+  <p>Download Eclipse Installer from <a href="//eclipse.org/downloads">http://www.eclipse.org/downloads</a></p>
 <?php endif;?>
 <!--
 <img class="img-responsive" src="assets/public/images/installer-instructions-01.png" alt="Screenshot of Eclipse Installer's web page.">
@@ -71,8 +76,10 @@
 <p>Once the installation is complete you can now launch Eclipse.
 The Eclipse Installer has done it's work. Happy coding.</p>
 <img class="img-responsive" src="/downloads/assets/public/images/installer-instructions-05.png" alt="Screenshot of the Launch window.">
+<?php if ($this->getAllowToggle()) :?>
 <p class="text-right padding-top-25">
   <a class="btn btn-warning btn-sm" data-target="#collapseEinstaller" class="solstice-collapse orange" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="collapseEinstaller">
     <i class="fa fa-times"></i> Hide
   </a>
-</p>
\ No newline at end of file
+</p>
+<?php endif;?>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/tpl/downloadsProjects.tpl.php b/eclipse.org-common/classes/downloads/views/view.projects.php
similarity index 67%
rename from eclipse.org-common/classes/downloads/tpl/downloadsProjects.tpl.php
rename to eclipse.org-common/classes/downloads/views/view.projects.php
index 4af64a5..8172439 100644
--- a/eclipse.org-common/classes/downloads/tpl/downloadsProjects.tpl.php
+++ b/eclipse.org-common/classes/downloads/views/view.projects.php
@@ -1,20 +1,21 @@
 <?php
-/*******************************************************************************
- * Copyright (c) 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
- *    Eric Poirier (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
+ *   Christopher Guindon (Eclipse Foundation)
+ *   Eric Poirier (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
 ?>
-
-
 <!-- Downloads-item -->
 <div class="<?php print $project->getProjectsAttributes('container','class'); ?>" style="<?php print $project->getProjectsAttributes('container','style'); ?>">
-  <span class="downloads-logo vertical-align"><img height="<?php print $project->getProjectsAttributes('image','height'); ?>" alt="<?php print $project->getTitle(); ?>" src="<?php print $project->getLogo(); ?>"></span>
+  <span class="downloads-logo vertical-align"><img height="<?php print $project->getProjectsAttributes('image','height'); ?>" alt="<?php print $project->getTitle(); ?>" src="<?php print $project->getLogo(); ?>?version=2"></span>
   <p><?php print $project->getDescription(); ?></p>
   <p class="visible-xs visible-sm"><a href="<?php print $project->getDownloadUrl64Bit(); ?>" class="btn btn-warning btn-xs">Get it</a></p>
   <p class="visible-xs visible-sm downloads-items-hover-box-links"><a href="<?php print $project->getLearnMoreUrl(); ?>">Learn More</a></p>
diff --git a/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-a.tpl.php b/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-a.tpl.php
new file mode 100644
index 0000000..8346897
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-a.tpl.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
+?>
+
+<span class="downloads-logo vertical-align"><img height="50" alt="Promoted Downloads" src="<?php print $this->ad->getImage();?>"></span>
+<!--<h3 class="downloads-items-header">Deploy IBM Bluemix</h3>-->
+<p><?php print $this->ad->getBody();?></p>
+<p class="orange small"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</p>
+<p class="visible-xs visible-sm"><a href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>" class="btn btn-warning btn-xs">Get it</a></p>
+<p class="visible-xs visible-sm downloads-items-hover-box-links"><a href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>">Learn More</a></p>
+<div class="downloads-items-hover-box">
+  <h4 class="downloads-items-header"><?php print $this->ad->getTitle();?></h4>
+  <p class="downloads-items-hover-box-text"><?php print $this->ad->getBody();?></p>
+  <p><a href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>" class="btn btn-warning btn-xs"><i class="fa fa-star" aria-hidden="true"></i> Promoted Download</a></p>
+  <p class="downloads-items-hover-box-links"><a href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>">Learn More</a></p>
+</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-b.tpl.php b/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-b.tpl.php
new file mode 100644
index 0000000..d93adbd
--- /dev/null
+++ b/eclipse.org-common/classes/downloads/views/view.promotedDownloads.layout-b.tpl.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - initial API and implementation
+ *   Christopher Guindon (Eclipse Foundation)
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
+?>
+
+<div class="package-row clearfix zebra promo">
+  <div class="row vertical-align-min-md">
+    <div class="col-sm-3 icon"><img src="<?php print $this->ad->getImage();?>" width="42" height="42" alt="<?php print $this->ad->getTitle();?>"/></div>
+    <div class="col-sm-13 text xs-sm-text-center">
+      <h3 class="title">
+        <a class="promo-title" href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>" title="<?php print $this->ad->getTitle();?>"><?php print $this->ad->getTitle();?></a>
+      </h3>
+      <p><?php print $this->ad->getBody();?></p>
+    </div>
+
+    <div class="col-sm-8 download">
+      <div class="col-sm-6 downloadLink-icon"><i class="fa fa-download"></i></div>
+        <div class="col-xs-24 col-sm-18 downloadLink-content">
+          <div class="text-center">
+            <p>
+              <a class="orange" href="//eclipse.org/go/<?php print $this->ad->getCampaign() . '?impression_id=' . $impression_id;?>" title="<?php print $this->ad->getTitle();?>">
+                <span class="text-center"><i class="fa fa-star"></i></span><br/>Promoted<br/>Download
+              </a>
+            </p>
+          </div>
+        </div>
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/contribution.class.php b/eclipse.org-common/classes/friends/contribution.class.php
index 6903d8a..1ef2394 100644
--- a/eclipse.org-common/classes/friends/contribution.class.php
+++ b/eclipse.org-common/classes/friends/contribution.class.php
@@ -16,7 +16,7 @@
 
   private $friend_id = "";
 
-  private $contribution_id = "";
+  private $contribution_id = NULL;
 
   private $date_expired = NULL;
 
@@ -119,7 +119,6 @@
       # insert
       $sql = "INSERT INTO " . $this->table_prefix . "friends_contributions (
           friend_id,
-          contribution_id,
           date_expired,
           amount,
           message,
@@ -129,7 +128,6 @@
         )
           VALUES (
           " . $App->returnQuotedString($App->sqlSanitize($this->getFriendID())) . ",
-          " . $App->returnQuotedString($App->sqlSanitize($this->getContributionID())) . ",
           " . $default_date_expired . ",
           " . $App->returnQuotedString($App->sqlSanitize($this->getAmount())) . ",
           " . $App->returnQuotedString($App->sqlSanitize($this->getMessage())) . ",
diff --git a/eclipse.org-common/classes/friends/donation.class.php b/eclipse.org-common/classes/friends/donation.class.php
index 35b012f..d7d4ffc 100644
--- a/eclipse.org-common/classes/friends/donation.class.php
+++ b/eclipse.org-common/classes/friends/donation.class.php
@@ -11,7 +11,6 @@
  *******************************************************************************/
 require_once(realpath(dirname(__FILE__) . "/../../system/session.class.php"));
 require_once(realpath(dirname(__FILE__) . "/../../system/app.class.php"));
-require_once(realpath(dirname(__FILE__) . "/../../system/cookies.class.php"));
 require_once("donor.class.php");
 require_once("donationEmails.class.php");
 
@@ -28,11 +27,6 @@
   private $App = NULL;
 
   /**
-   * Cookies
-   */
-  private $Cookies = NULL;
-
-  /**
    * Donation amount.
    */
   public $donation_amount = 0;
@@ -83,6 +77,34 @@
   public $donation_status = "";
 
   /**
+   * Donation landing page
+   *
+   * @var string
+   */
+  public $donation_landing_page = NULL;
+
+  /**
+   * Donation file_id
+   *
+   * @var integer
+   */
+  public $donation_file_id = NULL;
+
+  /**
+   * Donation scope
+   *
+   * @var string
+   */
+  public $donation_scope = NULL;
+
+  /**
+   * Donation campaign
+   *
+   * @var string
+   */
+  public $donation_campaign = NULL;
+
+  /**
    * If this is a subscription donation or not.
    *
    * @var unknown
@@ -107,7 +129,6 @@
     }
     $this->Donor = new Donor($test_mode);
     $this->App = new App();
-    $this->Cookies = new Cookies();
   }
 
   /**
@@ -313,6 +334,54 @@
   }
 
   /**
+   * Get $donation_landing_page
+   *
+   * @return string
+   */
+  public function get_donation_landing_page() {
+    if (empty($this->donation_landing_page)){
+      $this->set_donation_landing_page('donate');
+    }
+    return strtoupper($this->donation_landing_page);
+  }
+
+  /**
+   * Get $donation_file_id
+   *
+   * @return string
+   */
+  public function get_donation_file_id() {
+    if (!is_numeric($this->donation_file_id)) {
+      $this->donation_file_id = NULL;
+    }
+    return $this->donation_file_id;
+  }
+
+  /**
+   * Get $donation_scope
+   *
+   * @return string
+   */
+  public function get_donation_scope() {
+    if (!is_string($this->donation_scope)) {
+      $this->donation_scope = NULL;
+    }
+    return $this->donation_scope;
+  }
+
+  /**
+   * Get $donation_campaign
+   *
+   * @return string
+   */
+  public function get_donation_campaign() {
+    if (!is_string($this->donation_campaign)) {
+      $this->donation_campaign = NULL;
+    }
+    return $this->donation_campaign;
+  }
+
+  /**
    * Get donation_subscription value
    *
    * @return unknown
@@ -321,7 +390,6 @@
     return (int)$this->donation_subscription;
   }
 
-
   /**
    * Get id for transaction
    * @param string $txn_id
@@ -355,7 +423,7 @@
     }
 
     // Format the amount
-    $donation_amount = number_format($donation_amount, 2);
+    $donation_amount = number_format($donation_amount, 2, '.', '');
 
     $this->donation_amount = $donation_amount;
     $this->_set_donation_benefit_level();
@@ -374,22 +442,18 @@
    * Set donation currency type
    */
   public function set_donation_currency($currency = '') {
-    $valid_currency = array('USD', 'BTC');
-    $valid_type = array('PAYPAL', 'BITPAY');
+    $valid_currency = array('USD');
+    $valid_type = array('PAYPAL');
     $currency = strtoupper($currency);
     if (in_array($currency, $valid_currency)) {
       $this->donation_currency = $currency;
     }
     // We might be passing $paymentGateway->gateway_type and
-    // we know that we only accept USD for paypal and BTC from bitcoin.
+    // we know that we only accept USD for paypal.
     elseif (in_array($currency, $valid_type)) {
       if ($currency == 'PAYPAL') {
          $this->donation_currency = 'USD';
       }
-      // @todo: verify if will accept more currencies with bitpay.
-      elseif ($currency == 'BITPAY') {
-        $this->donation_currency = 'BTC';
-      }
     }
   }
 
@@ -399,8 +463,8 @@
    * @param unknown $value
    */
   public function set_donation_is_anonymous($value) {
-    $this->donation_is_anonymous = 1;
-    if ($value != "is_anonymous" && $value != 1) {
+  $this->donation_is_anonymous = 1;
+    if ($value == 'recognition' || ($value === 0 || $value === '0')) {
       $this->donation_is_anonymous = 0;
     }
   }
@@ -442,7 +506,6 @@
       'completed', // paypal payment_status
       'no_eclipse_id', // Completed but addionnal steps are required to link donation with eclipse_id.
       'new_donation_form', // This was created by the process.php script.
-      'confirmed' // bitpay payment status
     );
 
     if (in_array($status, $available_status)) {
@@ -451,6 +514,61 @@
   }
 
   /**
+   * Set donation $landing_page
+   *
+   * @param string $page
+   */
+  public function set_donation_landing_page($page) {
+    $page = strtolower($page);
+    $available = array(
+      'donate', // eclipse.org/donate/
+      'download', // eclipse.org/downloads/
+      'eclipse_ide', // eclipse.org/donate/ide/
+    );
+
+    if (in_array($page, $available)) {
+      $this->donation_landing_page = strtoupper($page);
+    }
+  }
+
+    /**
+   * Get $donation_file_id
+   *
+   * @return string
+   */
+  public function set_donation_file_id($file_id) {
+    if (!empty($file_id) && is_numeric($file_id) && $file_id <= 2147483647){
+      $this->donation_file_id = $file_id;
+    }
+
+    return $this->donation_file_id;
+  }
+
+  /**
+   * Get $donation_scope
+   *
+   * @return string
+   */
+  public function set_donation_scope($scope = "") {
+    if (!empty($scope) && is_string($scope)){
+      $this->donation_scope = substr($scope, 0, 128);
+    }
+    return $this->donation_scope;
+  }
+
+  /**
+   * Get $donation_campaign
+   *
+   * @return string
+   */
+  public function set_donation_campaign($campaign = "") {
+    if (!empty($campaign) && is_string($campaign)){
+      $this->donation_campaign = substr($campaign, 0, 128);
+    }
+    return $this->donation_campaign;
+  }
+
+  /**
    * Set donation subscription value
    * @param string $donation_subscription
    */
@@ -491,6 +609,10 @@
       $this->set_donation_message($process['message']);
       $this->set_donation_subscription($process['subscription']);
       $this->set_donation_is_anonymous($process['is_anonymous']);
+      $this->set_donation_landing_page($process['landing_page']);
+      $this->set_donation_file_id($process['file_id']);
+      $this->set_donation_scope($process['scope']);
+      $this->set_donation_campaign($process['campaign']);
       $this->Donor->set_donor_email($process['email']);
       $this->Donor->set_donor_paypal_email($process['email_paypal']);
       $this->Donor->set_donor_uid($process['uid']);
@@ -528,188 +650,4 @@
     $content = $DonationEmails->send_email();
   }
 
-  /**
-   * Output the HTML of the Banner Ad
-   *
-   * return string
-   */
-  public function outputBannerAd() {
-
-    // Don't display the banner if the date is greater than Sept 30, 2016
-    if(date("Y/m/d") > "2016/09/30") {
-      return FALSE;
-    }
-
-    $banner_cookie = $this->getBannerCookies();
-
-    // Check if the banner should NOT be visible
-    // By default the visible value is 1
-    // The banner should not be visible if the value is anything but 1
-    if (!isset($banner_cookie['donation_banner']['value']['visible']) || $banner_cookie['donation_banner']['value']['visible'] !== 1) {
-      return FALSE;
-    }
-
-    // Don't print the banner if the user is on the donate page or sub pages
-    if (strpos($this->App->getCurrentURL(), '/donate/') !== FALSE) {
-      return FALSE;
-    }
-
-    // Set the default content if the cookie is empty
-    if (!isset($banner_cookie['donation_banner']['value']['template'])) {
-      $banner_cookie['donation_banner']['value']['template'] = 1;
-    }
-
-    // Set the correct content for the template
-    switch ($banner_cookie['donation_banner']['value']['template']) {
-      case 1:
-        $banner_content['title']    = '<h2>September Friend Campaign</h2>';
-        $banner_content['text']     = '<p>Friends of Eclipse,</p>
-                                       <p>Eclipse is an open source community that benefits millions of developers around
-                                       the world each and every day! During the month of September, we are asking you
-                                       to give back to our wonderful open source community. All donations will be used
-                                       to improve Eclipse technology. Your contribution counts!</p>';
-        $banner_content['thankyou'] = '<p>We thank you for this gesture, and for giving back to our community. <i class="fa fa-heart"></i></p>';
-        $banner_content['campaign'] = "PROMO_DONATE_BANNER_1";
-        break;
-      case 2:
-        $banner_content['title']    = '<h2>September Friend Campaign</h2>';
-        $banner_content['text']     = '<p>Calling all Eclipse community members,</p>
-                                       <p>This month we are asking you to support the future of the Eclipse community.
-                                       Show your support for Eclipse by donating today. All donations will be used to
-                                       improve the Eclipse platform.</p>';
-        $banner_content['thankyou'] = '<p>Thank you for giving back! <i class="fa fa-heart"></i></p>';
-        $banner_content['campaign'] = "PROMO_DONATE_BANNER_2";
-        break;
-      case 3:
-        $banner_content['title']    = '<h2>September Friend Campaign</h2>';
-        $banner_content['text']     = '<p>Friends of Eclipse,</p>
-                                       <p>Eclipse is a free IDE used by millions of developers every day. If each
-                                       developer donates the price of a coffee or beer, we can fund some amazing
-                                       improvements to Eclipse. Please donate today.</p>';
-        $banner_content['thankyou'] = '<p>Thank you for giving back! <i class="fa fa-heart"></i></p>';
-        $banner_content['campaign'] = "PROMO_DONATE_BANNER_3";
-        break;
-      case 4:
-        $banner_content['title']    = '<h2>September Friend Campaign</h2>';
-        $banner_content['text']     = '<p>Eclipse Users,</p>
-                                       <p>For 15 years, Eclipse has been providing great development tools and they are
-                                       free! Today we need your support to fund the ongoing development of the Eclipse
-                                       platform. Please donate and support Eclipse.</p>';
-        $banner_content['thankyou'] = '<p>Thank you for giving back! <i class="fa fa-heart"></i></p>';
-        $banner_content['campaign'] = "PROMO_DONATE_BANNER_4";
-        break;
-    }
-
-    // Print the output if the user is a commiter
-    ob_start();
-    include("tpl/donate_ad.tpl.php");
-    return ob_get_clean();
-  }
-
-  /**
-   * Get the Banner Ad cookies
-   *
-   * return array
-   */
-  public function getBannerCookies() {
-
-    // json decoded cookie
-    $cookies = $this->Cookies->getCookie();
-
-    // Default value of the reset cookie
-    $reset_cookies = FALSE;
-
-    // If the current date is greater or equal to sept 15
-    if (date("Y/m/d") >= "2016/09/15") {
-
-      // By default we don't want to assume
-      // we need to reset the cookie yet
-      $reset_cookies = TRUE;
-
-      // If the reset cookie has been set and the value is 1
-      // this means that we already have resetted the cookie
-      // and don't need to do it again
-      if (isset($cookies['donation_banner']['value']['reset']) && $cookies['donation_banner']['value']['reset'] == 1) {
-        $reset_cookies = FALSE;
-      }
-    }
-
-    // Check if the cookie is not empty
-    // And if the cookie is not reseting
-    if (!empty($cookies) && !$reset_cookies) {
-
-      $template = $cookies['donation_banner']['value']['template'];
-      $banner_expiration = $cookies['donation_banner']['value']['banner_expiration'];
-
-      // Check if the expiration data has been set AND has expired
-      // We don't need to go through the loop if the user is seeing the template #4
-      if (isset($banner_expiration) && time() > $banner_expiration && $template !== 4) {
-
-        for ($t = 1; $t <= 3; $t++) {
-          // Check what template is currently being displayed
-          if ($cookies['donation_banner']['value']['template'] == $t) {
-
-            // Update the cookie with the next template
-            // for another 24 hours
-            return $this->_setCookieData($t + 1);
-          }
-        }
-
-      }
-      return $cookies;
-    }
-
-    // If the cookie is not set,
-    // set and return the default values
-    return $this->_setCookieData(1, 1, '', '', $reset_cookies);
-  }
-
-  /**
-   * Set the cookie data
-   *
-   * @param string $name - Name of the cookie item that will be stored
-   * @param int $template - Template number
-   * @param string $banner_expiration - Expiration of the item
-   * @param int $visible
-   * @param string $expiration
-   * @param bool $reset
-   *
-   * @return array
-   */
-  private function _setCookieData($template = NULL, $visible = 1, $banner_expiration = "", $expiration = "", $reset = NULL) {
-
-    if (is_null($template) || !is_numeric($visible)) {
-      return FALSE;
-    }
-
-    // If the cookie is reseting,
-    // return its state to 0
-    // so it doesn't reset a second time
-    $reset_value = 0;
-    if ($reset) {
-      $reset_value = 1;
-    }
-
-    // Set the default banner expiration date if empty
-    if (empty($banner_expiration)) {
-      $banner_expiration = strtotime('+1 day');
-    }
-
-    // Set the default expiration date if empty
-    if (empty($expiration)) {
-      $expiration = strtotime('+1 month');
-    }
-
-    $data = array(
-      'value' => array(
-        'template' => $template,
-        'banner_expiration' => $banner_expiration,
-        'visible' => $visible,
-        'reset' => $reset_value,
-      ),
-      'expiration' => $expiration,
-    );
-    $this->Cookies->setCookies('donation_banner',$data['value'], $data['expiration']);
-    return array('donation_banner' => $data);
-  }
 }
diff --git a/eclipse.org-common/classes/friends/donationEmails.class.php b/eclipse.org-common/classes/friends/donationEmails.class.php
index f8b0097..6cf7116 100644
--- a/eclipse.org-common/classes/friends/donationEmails.class.php
+++ b/eclipse.org-common/classes/friends/donationEmails.class.php
@@ -167,7 +167,7 @@
 
     // To make browsing the log table easier
     $EventLog->setLogTable("__paypal.class");
-    $EventLog->setPK2($_SERVER['REMOTE_ADDR']);
+    $EventLog->setPK2($this->App->getRemoteIPAddress());
     $EventLog->insertModLog($transaction_id);
     return $this->email_content;
   }
diff --git a/eclipse.org-common/classes/friends/donationList.class.php b/eclipse.org-common/classes/friends/donationList.class.php
deleted file mode 100644
index 0fc4bb6..0000000
--- a/eclipse.org-common/classes/friends/donationList.class.php
+++ /dev/null
@@ -1,345 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-require_once(realpath(dirname(__FILE__) . "/../../system/smartconnection.class.php"));
-require_once("friendsContributionsList.class.php");
-
-/**
- * Helper class to display donation information
- *
- * @todo: Clean up the code
- *  This code was mostly written by Eddie and I created a class to scope his work.
- *  The code is hard to understand and needs a bit of love.
- *
- * @author chrisguindon
- *
- */
-class DonationList {
-
-  private $App = NULL;
-
-  private $table_prefix = "";
-
-  private $test_mode = FALSE;
-
-  public function __construct($test_mode = FALSE){
-    $this->App = new App();
-    if ($test_mode == TRUE){
-      $this->test_mode = TRUE;
-      $this->table_prefix = 'testing_';
-    }
-  }
-
-  /**
-   * Donor list for the sidebar
-   *
-   * @param number $_numrows
-   * @param number $offset
-   */
-  public function sideDonorList($_numrows, $offset) {
-
-    $friendsContributionsList = new FriendsContributionsList($this->test_mode);
-    $friendsContributionsList->selectFriendsContributionsList($offset, $_numrows);
-
-    $friend = new Friend($this->test_mode);
-    $contribution = new Contribution($this->test_mode);
-    $fcObject = new FriendsContributions($this->test_mode);
-
-    $count = $friendsContributionsList->getCount();
-    for ($i=0; $i < $count; $i++) {
-      $fcObject = $friendsContributionsList->getItemAt($i);
-      $friend = $fcObject->getFriendObject();
-      $contribution = $fcObject->getContributionObject();
-      $date = $contribution->getDateExpired();
-      $date = strtotime($date);
-      $date = strtotime("-1 year", $date);
-      $now = strtotime("now");
-      if ($date <= $now) {
-        $anonymous = $friend->getIsAnonymous();
-        if ($anonymous != 1) {
-          $name = $friend->getFirstName() . " " . $friend->getLastName();
-          $name = htmlentities($name);
-        }
-        else
-          $name = "Anonymous";
-          $benefit = $friend->getIsBenefit();
-          $star = '<i class="fa fa-li fa-angle-double-right"></i> ';
-          if ($benefit) {
-            $star = '<i class="fa fa-li fa-star"></i> ';
-          }
-          $amount = $contribution->getAmount();
-          echo "<li>" . $star .  $name . "-" . "$" . $amount . "</li>";
-        }
-    }
-    echo "<div class=\"more\"><a href=\"donorlist.php\">Donor List</a></div>";
-  }
-
-  /**
-   * Get HTML to display donor list table
-   *
-   * @param number $_numrows
-   * @param number $offset
-   * @param string $chevron
-   * @param string $striped
-   */
-  function donorListTable($_numrows, $offset = 0, $chevron = TRUE, $striped = TRUE) {
-    $return_html = "";
-    if ($striped) $return_html .= "<table class='table table-striped'>";
-    else $return_html .= "<table class='table'>";
-    $chevron_html = '<i class="fa fa-li fa-chevron-circle-right orange" style="position: relative; left: 0px; width: 0px;"></i> ';
-
-    $friendsContributionsList = new FriendsContributionsList($this->test_mode);
-    $friendsContributionsList->selectFriendsContributionsList($offset, $_numrows);
-
-    $friend = new Friend($this->test_mode);
-    $contribution = new Contribution($this->test_mode);
-    $fcObject = new FriendsContributions($this->test_mode);
-
-    $count = $friendsContributionsList->getCount();
-    for ($i=0; $i < $count; $i++) {
-      $fcObject = $friendsContributionsList->getItemAt($i);
-      $friend = $fcObject->getFriendObject();
-      $contribution = $fcObject->getContributionObject();
-      $anonymous = $friend->getIsAnonymous();
-      $date = $contribution->getDateExpired();
-      $date = strtotime($date);
-      $date = strtotime("-1 year", $date);
-      $now = strtotime("now");
-      if ($date <= $now) {
-        if ($anonymous != 1 && ($friend->getFirstName() != '' || $friend->getLastName() != '')) {
-          $name = $friend->getFirstName() . " " . $friend->getLastName();
-          $name = htmlentities($name);
-        } else {
-          $name = "Anonymous";
-        }
-        $amount = $contribution->getAmount();
-        if ($chevron) $return_html .= "<tr><td>$chevron_html</td><td>$name-\$$amount</td></tr>";
-        else $return_html .= "<tr><td>$name-\$$amount</td></tr>";
-      }
-    }
-    $return_html .= "</table>";
-    return $return_html;
-  }
-
-  /**
-   * Get HTML for a display pager
-   *
-   * @param number $_start
-   * @param number $_pageValue
-   * @param number $_pageCount
-   * @param string $_startParam
-   * @param string $_anchor
-   */
-  public function displayPager($_start, $_pageValue, $_pageCount, $_startParam = 'start', $_anchor = '') {
-      // Build URL
-      $next = $_SERVER['PHP_SELF'] . '?' . $_startParam . '=' . ($_start + $_pageValue) . '' . $_anchor;
-      $previous = $_SERVER['PHP_SELF'] . '?' . $_startParam . '=' . ($_start - $_pageValue) . '' . $_anchor;
-    ob_start();
-    ?>
-    <table class="pager">
-        <tr>
-          <td style="text-align:left">
-        <?php
-          if ($_start >= $_pageValue) {
-                      ?><a href="<?php print $previous;?>">&lt;&lt; Previous Page</a><?php
-          }
-        ?>&nbsp;</td>
-          <td style="text-align:right">
-        <?php
-          if (($_start + $_pageValue) < $_pageCount) {
-                      ?><a href="<?php print $next;?>">Next Page &gt;&gt;</a><?php
-          }
-        ?>
-          </td>
-        </tr>
-      </table>
-    <?php
-    return ob_get_clean();
-  }
-
-  /**
-   * Get HTML for donation table list
-   *
-   * @param array $contributions
-   */
-  public function displayTable($contributions) {
-      echo '<table class="table table-hover table-condensed" cellspacing=0>' .
-             '<tr class="donorHeader">' .
-               '<td colspan="2" width="60%">Name and Message</td>' .
-               '<td width="20%">Date</td>' .
-               '<td width="20%" align="right">Amount</td>' .
-             '</tr>';
-      // Get total number of items so we can know whether to page or not.
-      $friend = new Friend($this->test_mode);
-      $contribution = new Contribution($this->test_mode);
-      $fcObject = new FriendsContributions($this->test_mode);
-      foreach ($contributions as $contribution) {
-          $contrib = $contribution->getContributionObject();
-          $friend = $contribution->getFriendObject();
-          $anonymous = $friend->getIsAnonymous();
-          if ($anonymous != 1 && ($friend->getFirstName() != '' || $friend->getLastName() != ''))
-              $name = $friend->getFirstName() . " " . $friend->getLastName();
-          else $name = "Anonymous";
-          $benefit = $friend->getIsBenefit();
-          if ($benefit != 0) $benefit = " <img width='25' src=\"images/stars.png\">";
-          else $benefit = "";
-          $amount = $contrib->getAmount();
-          if (strpos($amount, ".") == 0) {
-              $amount = $amount . ".00";
-          }
-          $currency = $contrib->getCurrency();
-          $comment =  stripslashes(strip_tags($contrib->getMessage()));
-          if (strlen($comment) > 80) {
-              if (strpos($comment, ' ') == 0) {
-                  $commentArray = str_split($comment, 80);
-                  $comment = 0;
-                  foreach ($commentArray as $value) {
-                      $comment .= $value . " ";
-                  }
-              }
-          }
-          $currency = ($currency === 'USD') ? 'USD' : 'BTC';
-          $date = strtotime("-1 year", strtotime($contrib->getDateExpired()));
-          $now = strtotime("now");
-          if ($date <= $now) {
-              $date = date("Y-m-d", $date);
-              echo '<tr class="donorRecord">' .
-                   '<td width="25">' . $benefit . '</td>' .
-                   '<td width="59%"><b>' . $name . '</b><br/>' . $comment . '</td>' .
-                   '<td>' . $date . '</td>' .
-                   '<td align="right">$' . $amount . '</td>' .
-                   '</tr>';
-          }
-      }
-      echo '</table>';
-  }
-
-  /**
-   * Get gravatar URL
-   *
-   * @param string $email
-   * @param number $size
-   * @param string $default
-   */
-  public function getGravatarURL($email, $size = 80, $default = 'mm') {
-    return "https://secure.gravatar.com/avatar/" . md5(strtolower(trim($email))) . "?d=" . $default . "&s=" . $size;
-  }
-
-  /**
-   * Get html for displaying a Friend of Eclipse
-   *
-   * @param stdClass $friendsContributions
-   * @param string $template
-   */
-  public function displayFriends($friendsContributions, $template = 'default') {
-      $results = array();
-
-      foreach ($friendsContributions as $contributions) {
-        $result = array();
-        $result['Friend'] = $contributions->getFriendObject();
-        $name = ucwords(strtolower($result['Friend']->getFirstName())) . ' ' . ucwords(strtolower($result['Friend']->getLastName()));
-        if ($name == " ") {
-          $name = 'Anonymous';
-        }
-        $result['name'] = $name;
-        $results[] = $result;
-      }
-      return $this->_get_donationlist_template($results, $template);
-  }
-
-  /**
-   * Get Friend count
-   *
-   * @param string $get_anonymous
-   * @param string $get_expired
-   * @param number $donation_minimum
-   * @return Ambigous <>
-   */
-  public function getFriendsCount($get_anonymous = TRUE, $get_expired = TRUE, $donation_minimum = 35) {
-      $friends = array();
-      $sql = "SELECT COUNT(*) FROM " . $this->table_prefix . "friends_contributions as FC
-              LEFT JOIN " . $this->table_prefix . "friends AS F ON FC.friend_id = F.friend_id WHERE FC.amount >= " . $this->App->sqlSanitize($donation_minimum);
-      if (!$get_anonymous) $sql .= " AND F.is_anonymous = 0";
-      if (!$get_expired) $sql .= " AND FC.date_expired > NOW()";
-      $result = $this->App->eclipse_sql($sql);
-      $row = mysql_fetch_row($result);
-      return $row[0];
-  }
-
-  /**
-   * Example for importing t-shirt code in the Eclipse database
-   */
-  public function importCode() {
-    $codes_file = 'codes.csv';
-    $con = mysqli_connect("dbmaster","user_here","password_here", "eclipse");
-
-    $f = fopen($codes_file, 'r');
-    while ($line = fgets($f)) {
-      $line = trim($line);
-      $line = trim($line, ',');
-      $data = explode(',', $line);
-      $data[2] = $this->_donationlist_fix_date($data[2]);
-      $sql = 'INSERT INTO " . $this->table_prefix . "tshirts VALUES ("' . $data[0] . '", "' . $data[1] . '", \'' . $data[2] . '\', null, null, null)';
-      mysqli_query($con,$sql);
-    }
-  }
-
-  /**
-   * Alter date for tshirts table
-   *
-   * @param string $date_str
-   * @return string
-   */
-  private function _donationlist_fix_date($date_str) {
-    $d = explode('/', $date_str);
-    return $d[2] . "-" . $d[0] . "-" . $d[1];
-  }
-
-  /**
-   * Get template for displaying a friend
-   *
-   * @param unknown $results
-   * @param string $template
-   */
-  private function _get_donationlist_template($results, $template = 'default'){
-    if ($template === 'four-columns') {
-     $results = array_chunk($results, 10);
-    }
-    else {
-      $rebuild = array();
-      foreach($results as $r){
-        $rebuild[] = array_merge($r, $this->_getLDAPinfo($r['Friend']));
-      }
-      $results = $rebuild;
-    }
-
-    ob_start();
-    include('tpl/displayfriend-'. $template . '.tpl.php');
-    return  ob_get_clean();
-  }
-
-  /**
-   * Get LDAP info for a Friend
-   * @param unknown $Friend
-   */
-  private function _getLDAPinfo($Friend){
-   require_once("/home/data/httpd/eclipse-php-classes/system/ldapconnection.class.php");
-   $ldap = new LDAPConnection();
-   $result = array();
-   $result['uid'] = $Friend->getLDAPUID();
-   $result['mail'] = $Friend->getEmail();
-   if ($result['uid'] && $result['mail'] != "") {
-     $dn = $ldap->getDNFromUID($result['uid']);
-     $result['mail'] = $ldap->getLDAPAttribute($dn, 'mail');
-   }
-   return $result;
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/donor.class.php b/eclipse.org-common/classes/friends/donor.class.php
index fb69bce..519fe76 100644
--- a/eclipse.org-common/classes/friends/donor.class.php
+++ b/eclipse.org-common/classes/friends/donor.class.php
@@ -302,7 +302,7 @@
   /**
    * Shortcut for setting the donation transaction id
    *
-   * For paypal, this is the txn_id but for bitpay its the invoice id.
+   * For paypal, this is the txn_id.
    *
    * @param string $txn_id
    */
diff --git a/eclipse.org-common/classes/friends/friend.class.php b/eclipse.org-common/classes/friends/friend.class.php
index 1f86ed2..bb6aeec 100755
--- a/eclipse.org-common/classes/friends/friend.class.php
+++ b/eclipse.org-common/classes/friends/friend.class.php
@@ -134,11 +134,11 @@
   }
 
   function setFirstName($_first_name) {
-    $this->first_name = $_first_name;
+    $this->first_name = preg_replace('/[<>]/', '', $_first_name);
   }
 
   function setLastName($_last_name) {
-    $this->last_name = $_last_name;
+    $this->last_name = preg_replace('/[<>]/', '', $_last_name);
   }
 
   function setDateJoined($_date_joined) {
diff --git a/eclipse.org-common/classes/friends/friendsContributionsList.class.php b/eclipse.org-common/classes/friends/friendsContributionsList.class.php
deleted file mode 100644
index b271681..0000000
--- a/eclipse.org-common/classes/friends/friendsContributionsList.class.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2007-2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Nathan Gervais (Eclipse Foundation)- initial API and implementation
- *    Denis Roy (Eclipse Foundation)
- *******************************************************************************/
-require_once(realpath(dirname(__FILE__) . "/../../system/smartconnection.class.php"));
-require_once("friendsContributions.class.php");
-
-class FriendsContributionsList {
-
-  var $list = array();
-
-  private $table_prefix = "";
-
-  public function __construct($testmode = FALSE) {
-    if ($testmode === TRUE){
-      $this->table_prefix = 'testing_';
-    }
-  }
-
-  function getList() {
-    return $this->list;
-  }
-
-  function setList($_list) {
-    $this->list = $_list;
-  }
-
-  function add($_contribution) {
-    $this->list[count($this->list)] = $_contribution;
-  }
-
-  function getCount() {
-    return count($this->list);
-  }
-
-  function getItemAt($_pos) {
-    if($_pos < $this->getCount()) {
-      return $this->list[$_pos];
-    }
-  }
-
-  function selectFriendsContributionsList($_start = -1, $_numrows = -1, $_where=NULL) {
-    $App = new App();
-    # the IF() for date_expired is a bad hack to accommodate the donor list, should we decide to extend all our friends by one month
-    $sql = "SELECT DISTINCT /* selectFriendsContributionsList */
-          F.first_name,
-          F.last_name,
-          F.bugzilla_id,
-          F.is_anonymous,
-          F.is_benefit,
-          F.uid,
-          F.date_joined,
-          FC.friend_id,
-          IF(FC.date_expired > DATE_ADD(NOW(), INTERVAL 1 YEAR), DATE_SUB(FC.date_expired, INTERVAL 1 MONTH), FC.date_expired) AS date_expired,
-          FC.contribution_id,
-          FC.transaction_id,
-          FC.currency,
-          FC.process_id,
-          FC.amount,
-          FC.message,
-          UP.user_mail
-          FROM " . $this->table_prefix . "friends_contributions as FC
-          LEFT JOIN " . $this->table_prefix . "friends as F on FC.friend_id = F.friend_id
-          LEFT JOIN users_profiles as UP on (F.uid = UP.user_uid AND F.uid != '')";
-    if ($_where != NULL) {
-      $sql .= " " . $_where;
-    }
-        $sql .= " ORDER by FC.contribution_id DESC";
-    if ($_start >= 0)
-    {
-    $sql .= " LIMIT $_start";
-    if ($_numrows > 0)
-      $sql .= ", $_numrows";
-    }
-
-    $App->sqlSanitize($sql);
-    $result = $App->eclipse_sql($sql);
-
-    while($myrow = mysql_fetch_array($result)) {
-      $Friend = new Friend();
-      $Friend->setFriendID($myrow['friend_id']);
-      $Friend->setBugzillaID($myrow['bugzilla_id']);
-      $Friend->setDateJoined($myrow['date_joined']);
-      $Friend->setFirstName($myrow['first_name']);
-      $Friend->setLastName($myrow['last_name']);
-      $Friend->setIsAnonymous($myrow['is_anonymous']);
-      $Friend->setIsBenefit($myrow['is_benefit']);
-      $Friend->setLDAPUID($myrow['uid']);
-      $Friend->setEmail($myrow['user_mail']);
-
-      $Contribution = new Contribution();
-      $Contribution->setFriendID($myrow['friend_id']);
-      $Contribution->setContributionID($myrow['contribution_id']);
-      $Contribution->setDateExpired($myrow['date_expired']);
-      $Contribution->setMessage($myrow['message']);
-      $Contribution->setAmount($myrow['amount']);
-      $Contribution->setCurrency($myrow['currency']);
-      $Contribution->setProcessId($myrow['process_id']);
-      $Contribution->setTransactionID($myrow['transaction_id']);
-
-      $FriendsContributions = new FriendsContributions();
-      $FriendsContributions->setFriendID($myrow['friend_id']);
-      $FriendsContributions->setContributionID($myrow['contribution_id']);
-      $FriendsContributions->setFriendObject($Friend);
-      $FriendsContributions->setContributionObject($Contribution);
-
-      $this->add($FriendsContributions);
-    }
-
-    $result = null;
-    $myrow  = null;
-  }
-}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/gateway/bitpay.class.php b/eclipse.org-common/classes/friends/gateway/bitpay.class.php
deleted file mode 100644
index c54234b..0000000
--- a/eclipse.org-common/classes/friends/gateway/bitpay.class.php
+++ /dev/null
@@ -1,1450 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation)- initial API and implementation
- *******************************************************************************/
-require_once(realpath(dirname(__FILE__) . "/../paymentGateway.class.php"));
-
-/**
- * Class for processing bitpay donations
- *
- * @author chrisguindon
- */
-class BitPay extends PaymentGateway {
-
-  /**
-   * Bitpay configurations
-   *
-   * @var array
-   */
-  private $bitpay_options = array();
-
-  /**
-   * Bitpay donation button data
-   *
-   * @var string
-   */
-  private $bitpay_data = "";
-
-  /**
-   * Bitpay API version
-   *
-   * @var string
-   */
-  private $bitpay_api_version = "";
-
-  /**
-   * Bitpay invoice response
-   * @var array
-   */
-  private $bitpay_invoice = NULL;
-
-  public function BitPay() {
-   parent::__construct();
-
-   // Overide debug settings on production
-   if (!$this->_get_debug_mode()) {
-     $this->_set_gateway_url('https://bitpay.com/checkout');
-     $this->_set_gateway_email('donate@eclipse.org');
-     $this->_set_bitpay_data('0aFzNGoToD0/elGC/2XEk0tokqlR/1w4f7ld6jMcYQ+/rt4oezJ7XvP5BWx0WmbDfgzQ0TFoBXp9fJ08yGxe9dz9EehQbo8t/kQvbWzhGDS0NZ1HUUOMQQktbomnBeW1Kgp46LS5c2EidjP+pG0vtQwzGJBcJIwZlHHJ1Ep8g5O2NAJrp8Fc9af2Gbfja7PTTwkO+KFOK78RwJ7rowxxCruqbyzQYk70I8e/89PoDlUjzRsI0xXyDE3Ssma8JxAeKOVoRw9Q+cIaLsLFKqwbqzZazE2tKQAo5GDmpz0uUWVB0sSwVQrCmO90uhQTq8zYrn8LUzAAofVnrteoVz3yKbqwV4TWXic+z6SN7UVroijSuNm22eUJXqZfgx4d9+ALtxits48RMpiPi0hZwUGBpw==');
-   }
-
-   $this->Donation->set_donation_currency('BTC');
-   $this->_set_gateway_type('bitpay');
-   $this->_set_gateway_notify_url('https://'. $this->_get_prefix_domain() . '/donate/web-api/bitpay.php');
-
-   $this->_set_bitpay_api_version('1.9');
-   $this->_set_bitpay_options();
-  }
-
-  /**
-   * Confirm donation from bitpay
-   */
-  private function _bitpay_confirm_ipn(){
-    $invoice = $this->_get_bitpay_invoice();
-    //@todo: Confirm this is the right way to validate an IPN response
-    if (isset($invoice['status']) && $invoice['status'] == 'confirmed') {
-      if (isset($invoice['url']) && !empty($invoice['url'])) {
-        return TRUE;
-      }
-    }
-    return FALSE;
-  }
-
-  /**
-   * Confirm and process IPN request
-   */
-  function bitpay_confirm_ipn() {
-    $this->_set_bitpay_invoice($this->bitpay_verify_notification());
-    // Validate the IPN response. If this is FALSE,
-    // it's quite probable that someone is trying to
-    // post fake data to the IPN script.
-
-    if ($this->_bitpay_confirm_ipn()) {
-      $values = $this->_get_bitpay_invoice();
-      $gateway_response = $this->_get_gateway_response();
-      if (!empty($gateway_response['posData'])){
-        $values['posData'] = $gateway_response['posData'];
-      }
-
-      // Confirm the transaction
-      // @todo: Support different payment_status like "pending" and "refund".
-      if (strtolower($values['status']) == 'confirmed'){
-        // Update Donor() with the info the user sent us before a donation
-        $update = FALSE;
-
-        if (!empty($values['id'])) {
-          // Verify if the transaction already exist.
-          $this->Donation->set_donation_txn_id($values['id']);
-          $this->Donation->Donor->set_donor_contribution_with_txn_id($this->Donation->get_donation_txn_id());
-        }
-
-        if (!empty($values['posData'])) {
-          $this->Donation->set_donation_random_invoice_id($values['posData']);
-          $update = $this->Donation->update_donor_from_process_table();
-        }
-
-        if (!empty($values['buyerFields']['buyerEmail'])) {
-          $this->Donation->Donor->set_donor_paypal_email($values['buyerFields']['buyerEmail']);
-        }
-
-        if (!empty($values['price'])){
-          $this->Donation->set_donation_amount($values['price']);
-        }
-
-        // Make sure the donation currency is set to USD
-        // If not, someone modified the currency before submitting the form
-        // We wont apply any benefits for this type of scenario
-        if (!empty($values['currency']) && $values['currency'] != 'USD'){
-          $invalid == TRUE;
-        }
-
-        if (!empty($values['status'])){
-          $this->Donation->set_donation_status($values['status']);
-        }
-
-        // If this is a new record, set the redirect url to the IPN
-        //
-        // I am assuming this would happend with a paypal
-        // donation without the custom field for
-        // the friends_process database table.
-        // This might happend with a bitpay donation.
-        if ($update === FALSE) {
-          $this->_set_gateway_redirect($this->_get_gateway_notify_url());
-        }
-
-        //Update donation if this is a valid transaction
-        if (!isset($invalid)) {
-          $this->update_friends_process_table($update);
-          // Update the friends_process table.
-          $this->Donation->update_donation_from_ipn($update);
-        }
-      }
-    }
-    $this->_email_ipn_post();
-  }
-
-  /**
-   * Implement _extend_email_ipn_post()
-   *
-   * @see Payment::_extend_email_ipn_post()
-   */
-  protected function _extend_email_ipn_post() {
-    print '-------Validation---------' . PHP_EOL;
-    print $this->_get_gateway_response() . PHP_EOL;
-    print '-------Invoice---------' . PHP_EOL;
-    print_r($this->bitpay_invoice) . PHP_EOL;
-    print '-------Identity Token---------' . PHP_EOL;
-    print $this->_get_gateway_auth_token() . PHP_EOL;
-  }
-
-  /**
-   * Implement _extend_set_debug_mode()
-   *
-   * @see Payment::_extend_set_debug_mode()
-   */
-  protected function _extend_set_debug_mode() {
-    $this->_set_gateway_url('https://test.bitpay.com/checkout');
-    $this->_set_bitpay_data('osjDxpBZPpOhQroIZfr6TT9xBh0V/WW9u+mGzbL6MDEkFQaCcQIdAqTfJsiKOtR02dYcKjGQbTkLVAZvVO7Ejp9T2ptc1PxevbI3FhmNNFffYL324/osufoFYvlOWRYX4EszvABx4x0cPrTMCrV23o4+u9USgA4xBRdprH94h2ZtnfJ6TYeY+RIGoDmeZhYgID2jESLiEISCFOmvXMZarYrB6V+9LRQcrMNTVmQYUbonL68L058l8eA2RRuAWFiT/mWXLrC/YkbMsF8+eMAeh+KlJ1sStUSHbWAmegQuwLM/1oddkK9+pFaT9ET0rkQPRa+cvtgCvsuYgTk/m2ueIAHWdaOz3TtNOuF3B743FsShQGLzhgzRA6CruYQZ+P/XNx1qz0cUfE4b+ayw/ZgqIa2YNfGxESp304u6F0hXvdw=');
-  }
-
-  /**
-   * Implement _set_gateway_auth_token()
-   *
-   * @see PaymentGateway::_set_gateway_auth_token()
-   */
-  protected function _set_gateway_auth_token() {
-    require_once("/home/data/httpd/eclipse-php-classes/system/authcode.php");
-    $this->gateway_auth_token = $payment_gateway_keys['bitpay']['production'];
-    if ($this->_get_debug_mode()){
-      $this->gateway_auth_token = $payment_gateway_keys['bitpay']['staging'];
-    }
-  }
-
-  /**
-   * Set bitpay API version
-   *
-   * @param string $version
-   */
-  protected function _set_bitpay_api_version($version = '') {
-    $this->bitpay_api_version = $version;
-  }
-
-  /**
-   * Get bitpay API verision
-   */
-  protected function _get_bitpay_api_version() {
-    return $this->bitpay_api_version;
-  }
-
-  /**
-   * Get bitpay invoice
-   */
-  protected function _get_bitpay_invoice() {
-    return $this->bitpay_invoice;
-  }
-
-  /**
-   * Get bitpay data for donation form
-   */
-  protected function _get_bitpay_data() {
-    return $this->bitpay_data;
-  }
-
-  /**
-   * Get bitpay default options
-   */
-  protected function _get_bitpay_options(){
-    return $this->bitpay_options;
-  }
-
-  /**
-   * Set bitpay data
-   */
-  protected function _set_bitpay_data($data = ''){
-    $this->bitpay_data = $data;
-  }
-
-  /**
-   * Set bitpay default OPTIONS
-   */
-  protected function _set_bitpay_options(){
-    /*
-     * Optional - url where the customer should be directed to after paying for the order
-     * example: $bitpay_NotificationUrl = 'http://www.example.com/confirmation.php';
-     */
-    $this->bitpay_options['redirectURL'] = $this->_get_gateway_return_url();
-
-    /*
-     * Boolean value.  Whether to verify POS data by hashing above api key.  If set to false, you should
-     * have some way of verifying that callback data comes from bitpay.com
-     * Note: this option can only be changed here.  It cannot be set dynamically.
-     */
-    $this->bitpay_options['verifyPos'] = FALSE;
-
-    /*
-     * REQUIRED!  This is the currency used for the price setting.  A list of other pricing
-     * currencies supported is found at bitpay.com
-     */
-    $this->bitpay_options['currency'] = $this->Donation->get_donation_currency();
-
-    /*
-     * Boolean value.  Indicates whether anything is to be shipped with
-     * the order (if false, the buyer will be informed that nothing is
-     * to be shipped)
-     */
-    $this->bitpay_options['physical'] = FALSE;
-
-    /*
-     * If set to false, then notificaitions are only
-     * sent when an invoice is confirmed (according the the
-     * transactionSpeed setting). If set to true, then a notification
-     * will be sent on every status change
-     */
-    $this->bitpay_options['fullNotifications'] = TRUE;
-
-    /*
-     * REQUIRED! Transaction speed: low/medium/high.  See API docs for more details.
-    */
-    $this->bitpay_options['transactionSpeed'] = 'low';
-
-    /*
-     * Boolean value. Change to 'true' if you would like automatic logging of errors.
-     * Otherwise you will have to call the error_logger function manually to log any information.
-     */
-    $this->bitpay_options['useLogging'] = TRUE;
-
-    /*
-     * Boolean value. Change to 'true' if you want to use the testnet development environment at
-     * test.bitpay.com. See: http://blog.bitpay.com/2014/05/13/introducing-the-bitpay-test-environment.html
-     * for more information on using testnet.
-     */
-    $this->bitpay_options['testnet'] = $this->_get_debug_mode();
-
-    /*
-     * Optional - email where you want invoice update notifications sent
-     */
-    $this->bitpay_options['notificationEmail'] = $this->_get_gateway_email();
-
-    /*
-     * Optional - url where bit-pay server should send payment notification updates.  See API doc for more details.
-     * Example: $bitpay_NotificationUrl = 'http://www.example.com/callback.php';
-     */
-    $this->bitpay_options['notificationURL'] = $this->_get_gateway_notify_url();
-  }
-
-  protected function _set_bitpay_invoice($invoice) {
-    if (is_array($invoice)) {
-      $this->bitpay_invoice = $invoice;
-    }
-  }
-  /**
-   * Returns the correct API service endpoint hostname depending on whether the
-   * production or test environment is selected.
-   *
-   * @param none
-   * @return string $host
-   */
-  function bitpay_host() {
-    /*
-     * Safety check in case an older version of the option file is being used or the test option is
-     * empty or not set at all.  Defaults to the live site.
-     */
-    if (!isset($this->bitpay_options['testnet']) || trim($this->bitpay_options['testnet']) == '' || is_null($this->bitpay_options['testnet']) || empty($this->bitpay_options['testnet']))
-      $this->bitpay_options['testnet'] == false;
-
-    if ($this->bitpay_options['testnet'] == true)
-      return 'test.bitpay.com';
-
-    return 'bitpay.com';
-  }
-
-  /**
-   * Handles post/get to BitPay via curl.
-   *
-   * @param string $url, boolean $post
-   * @return mixed $response
-   * @throws Exception $e
-   */
-  function bitpay_curl($url, $post = false) {
-
-    $apiKey = $this->_get_gateway_auth_token();
-
-    /*
-     * Container for our curl response or any error messages to return
-     * to the calling function.
-     */
-    $response = null;
-
-
-    if ((isset($url) && trim($url) != '') && (isset($apiKey) && trim($apiKey) != '')) {
-
-      try {
-        $curl = curl_init();
-
-        if (!$curl)
-          return 'Error in bitpay_curl(): Could not initialize a cURL handle!';
-
-        $content_length = 0;
-
-        if ($post) {
-          curl_setopt($curl, CURLOPT_POST, 1);
-          curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
-
-          $content_length = strlen($post);
-        }
-
-        $uname = base64_encode($apiKey);
-
-        if ($uname) {
-          $header = array(
-                    'Content-Type: application/json',
-                    'Content-Length: ' . $content_length,
-                    'Authorization: Basic ' . $uname,
-                    'X-BitPay-Plugin-Info: phplib' . $this->_get_bitpay_api_version(),
-                    );
-
-          /*
-           * If you are having SSL certificate errors due to an outdated CA cert on your webserver
-           * ask your webhosting provider to update your webserver.  The curl SSL checks are used
-           * to ensure you are actually communicating with the real BitPay network.
-           */
-          curl_setopt($curl, CURLOPT_URL, $url);
-          curl_setopt($curl, CURLOPT_PORT, 443);
-          curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
-          curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
-          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
-          curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
-          $this->_get_curl_options($curl);
-
-          /*
-           * Returns the error message or '' (the empty string) if no error occurred.
-           */
-          $responseString = curl_exec($curl);
-          /*
-           * For a complete list and description of all curl error codes
-           * see: http://curl.haxx.se/libcurl/c/libcurl-errors.html
-           */
-          $curl_error_number = curl_errno($curl);
-
-          if ($responseString === false || $curl_error_number != 0) {
-            if(function_exists('curl_strerror'))
-              $curl_error_description = curl_strerror($curl_error_number);
-             else
-               $curl_error_description = $this->bitpay_curl_Strerror($curl_error_number);
-
-            $response = array('error' => curl_error($curl), 'error_code' => $curl_error_number, 'error_code_description' => $curl_error_description);
-
-            if ($this->bitpay_options['useLogging'])
-              $this->error_logger('Error in bitpay_curl(): ' . $response);
-
-          } else {
-
-            if (function_exists('json_decode'))
-              $response = json_decode($responseString, true);
-            else
-              $response = $this->bitpay_JSON_decode($responseString);
-
-            if (!$response) {
-              $response = array('error' => 'invalid json');
-
-              if ($this->bitpay_options['useLogging'])
-                $this->error_logger('Error in bitpay_curl(): Invalid JSON.');
-            }
-
-          }
-          curl_close($curl);
-          $this->_set_gateway_response($response);
-          return $response;
-
-        } else {
-
-          curl_close($curl);
-
-          if ($this->bitpay_options['useLogging'])
-            $this->error_logger('Error in bitpay_curl(): Invalid data found in apiKey value passed to bitpay_curl. (Failed: base64_encode(apikey))');
-
-          return array('error' => 'Invalid data found in apiKey value passed to bitpay_curl. (Failed: base64_encode(apikey))');
-        }
-
-      } catch (Exception $e) {
-
-        /*
-         * It's possible that an error could occur before curl is initialized.  In that case
-         * it is safe to suppress the warning message from calling curl_close without an
-         * initialized curl session.
-         */
-        @curl_close($curl);
-
-        if ($this->bitpay_options['useLogging'])
-          $this->error_logger('Error in bitpay_curl(): ' . $e->getMessage());
-
-        return array('error' => $e->getMessage());
-      }
-
-    } else {
-
-      /*
-       * Invalid URL or API Key parameter specified
-       */
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_curl(): You must supply non-empty url and apiKey parameters.');
-
-      return array('error' => 'You must supply non-empty url and apiKey parameters to bitpay_curl().');
-    }
-
-  }
-
-  /**
-   * Creates BitPay invoice via bitpay_curl.  More information regarding the various options are explained
-   * below.  For the official API documentation, see: https://bitpay.com/downloads/bitpayApi.pdf
-   *
-   * @param string $orderId, string $price, string $posData, array $options
-   * @return array $response
-   * @throws Exception $e
-   */
-  function bitpay_create_invoice($orderId, $price, $posData = '', $options = array()) {
-
-    /*
-     * $orderId: Used to display an orderID to the buyer. In the account summary view, this value is used to
-     * identify a ledger entry if present. Maximum length is 100 characters.
-     *
-     * $price: by default, $price is expressed in the currency you set in bitpay__options.php.  The currency can be
-     * changed in $options.
-     *
-     * $posData: this field is included in status updates or requests to get an invoice.  It is intended to be used by
-     * the merchant to uniquely identify an order associated with an invoice in their system.  Aside from that, BitPay does
-     * not use the data in this field.  The data in this field can be anything that is meaningful to the merchant.
-     * Maximum length is 100 characters.
-     *
-     * Note:  Using the posData hash option will APPEND the hash to the posData field and could push you over the 100
-     *        character limit.
-     *
-     * $options keys can include any of:
-     *  'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
-     *  'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
-     *  'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone'
-     *
-     * If a given option is not provided here, the value of that option will default to what is found in bitpay__options.php
-     * (see api documentation for information on these options).
-     */
-
-    if (!isset($orderId) || is_null($orderId) || trim($orderId) == '' || empty($orderId))
-      return 'Error in bitpay_create_invoice(): No orderId supplied to function. Usage: bitpay_create_invoice($orderId, $price, $posData, $options)';
-
-    if (!isset($price) || is_null($price) || trim($price) == '' || empty($price))
-      return 'Error in bitpay_create_invoice(): No price supplied to function.  Usage: bitpay_create_invoice($orderId, $price, $posData, $options)';
-
-    try {
-      $options = array_merge($this->bitpay_options, $options);
-      $pos = array('posData' => $posData);
-
-      if ($this->bitpay_options['verifyPos'])
-        $pos['hash'] = $this->bitpay_hash(serialize($posData), $this->_get_gateway_auth_token());
-
-      if (function_exists('json_encode'))
-        $options['posData'] = json_encode($pos);
-      else
-        $options['posData'] = $this->bitpay_JSON_encode($pos);
-
-      if (strlen($options['posData']) > 100)
-        return array('error' => 'The posData exceeds the 100 character limit. Are you using the posData hash? The hash is APPENDED to the posData string and can cause overflow.');
-
-      $options['orderID'] = $orderId;
-      $options['price'] = $price;
-
-      $postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
-                           'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
-                           'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone');
-
-      foreach($postOptions as $o) {
-        if (array_key_exists($o, $options))
-          $post[$o] = $options[$o];
-      }
-
-      if (function_exists('json_encode'))
-        $post = json_encode($post);
-      else
-        $post = $this->bitpay_JSON_encode($post);
-
-      $response = $this->bitpay_curl('https://' . $this->bitpay_host() . '/api/invoice/', $this->_get_gateway_auth_token(), $post);
-
-      return $response;
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_create_invoice(): ' . $e->getMessage());
-
-      return array('error' => $e->getMessage());
-    }
-  }
-
-  /**
-   * Call from your notification handler to convert $_POST data to an object containing invoice data
-   *
-   * @return mixed $json
-   * @throws Exception $e
-   */
-  function bitpay_verify_notification() {
-    $apiKey = $this->_get_gateway_auth_token();
-
-    try {
-
-      /*
-       * There's a PHP quirk when reading a pure JSON POST response.  The $_POST global will be empty
-       * so you must read the raw POST input using file_get_contents().  For more information, see:
-       * https://support.bitpay.com/hc/en-us/articles/202596678-Blank-IPN-post-response-from-BitPay-when-using-PHP
-       */
-      $post = file_get_contents("php://input");
-
-      if (!$post)
-        return 'Error in bpVerifyNotification(): No POST data returned.';
-
-      if (function_exists('json_decode'))
-        $json = json_decode($post, true);
-      else
-        $json = bpJSONdecode($post);
-
-      if (is_string($json) || (is_array($json) && array_key_exists('error', $json)))
-        return $json;
-
-      if (!array_key_exists('posData', $json))
-        return 'Error in bitpay_verify_notification(): No posData found.';
-
-      if (function_exists('json_decode'))
-        $posData = json_decode($json['posData'], true);
-      else
-        $posData = $this->bitpay_JSON_decode($json['posData']);
-
-      if ($this->bitpay_options['verifyPos'] and $posData['hash'] != $this->bitpay_hash(serialize($posData['posData'])))
-        return 'Error in bitpay_verify_notification(): Authentication failed (bad hash)';
-
-      $json['posData'] = $posData['posData'];
-
-      if (!array_key_exists('id', $json))
-      {
-          return 'Cannot find invoice ID';
-      }
-      return $this->bitpay_get_invoice($json['id']);
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_verify_notification(): ' . $e->getMessage());
-
-      return array('error' => $e->getMessage());
-    }
-  }
-
-  /**
-   * Retrieves an invoice from BitPay.
-   *
-   * @param string $invoiceId
-   * @return mixed $json
-   * @throws Exception $e
-   */
-  function bitpay_get_invoice($invoiceId) {
-    $apiKey = $this->_get_gateway_auth_token();
-    if (!isset($invoiceId) || is_null($invoiceId) || trim($invoiceId) == '' || empty($invoiceId))
-      return 'Error in bitpay_get_invoice(): No invoiceId supplied to function. Usage: bitpay_get_invoice($invoiceId)';
-
-    try {
-      $response = $this->bitpay_curl('https://' . $this->bitpay_host() . '/api/invoice/' . $invoiceId);
-
-      if (is_string($response) || (is_array($response) && array_key_exists('error', $response)))
-        return $response;
-
-      if (function_exists('json_decode'))
-        $response['posData'] = json_decode($response['posData'], true);
-      else
-        $response['posData'] = $this->bitpay_JSON_decode($response['posData']);
-
-      $response['posData'] = $response['posData']['posData'];
-      return $response;
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_get_invoice(): ' . $e->getMessage());
-
-      return 'Error in bitpay_get_invoice(): ' . $e->getMessage();
-    }
-  }
-
-  /**
-   * Generates a base64 encoded keyed hash using the HMAC method. For more
-   * information, see: http://www.php.net/manual/en/function.hash-hmac.php
-   *
-   * @param string $data, string $key
-   * @return string $hmac
-   * @throws Exception $e
-   */
-  function bitpay_hash($data, $key) {
-
-
-    if (!isset($key) || is_null($key) || trim($key) == '' || empty($key))
-      return 'Error in bitpay_hash(): No key supplied to function. Usage: bitpay_hash($data, $key)';
-
-    if (!isset($data) || is_null($data) || trim($data) == '' || empty($data))
-      return 'Error in bitpay_hash(): No data supplied to function. Usage: bitpay_hash($data, $key)';
-
-    try {
-      $hmac = base64_encode(hash_hmac('sha256', $data, $key, TRUE));
-
-      return strtr($hmac, array('+' => '-', '/' => '_', '=' => ''));
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_hash(): ' . $e->getMessage());
-
-      return 'Error in bitpay_hash(): ' . $e->getMessage();
-    }
-  }
-
-  /**
-   * Decodes JSON response and returns an associative array.
-   *
-   * @param string $response
-   * @return array $arrResponse
-   * @throws Exception $e
-   */
-  function bitpay_decode_response($response) {
-
-
-    try {
-
-      if (!is_string($response) || is_null($response) || trim($response) == '' || empty($response))
-        return 'Error in bitpay_decode_response(): Missing response string parameter. Usage: bitpay_decode_response($response)';
-
-      if (function_exists('json_decode'))
-        return json_decode($response, true);
-      else
-        return $this->bitpay_JSON_decode($response);
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_decode_response(): ' . $e->getMessage());
-
-      return 'Error in bitpay_decode_response(): ' . $e->getMessage();
-    }
-  }
-
-  /**
-   * Retrieves a list of all supported currencies and returns an associative array.
-   *
-   * @param none
-   * @return array $currencies
-   * @throws Exception $e
-   */
-  function bitpay_currency_list() {
-
-
-    $currencies = array();
-    $rate_url = 'https://' . $this->bitpay_host() . '/api/rates';
-
-    try {
-
-      if (function_exists('json_decode'))
-        $clist = json_decode(file_get_contents($rate_url),true);
-      else
-        $clist = $this->bitpay_JSON_decode(file_get_contents($rate_url));
-
-      foreach($clist as $key => $value)
-        $currencies[$value['code']] = $value['name'];
-
-      return $currencies;
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_currency_list(): ' . $e->getMessage());
-
-      return 'Error in bitpay_currency_list(): ' . $e->getMessage();
-    }
-  }
-
-  /**
-   * Retrieves the current rate based on $code. The default code us USD, so calling the
-   * function without a parameter will return the current BTC/USD price.
-   *
-   * @param string $code
-   * @return string $rate
-   * @throws Exception $e
-   */
-  function bitpay_get_rate($code = 'USD') {
-    $rate = '';
-    $clist = '';
-    $rate_url = 'https://' . $this->bitpay_host() . '/api/rates';
-
-    try {
-
-      if (function_exists('json_decode'))
-        $clist = json_decode(file_get_contents($rate_url), true);
-      else
-        $clist = $this->bitpay_JSON_decode(file_get_contents($rate_url));
-
-      foreach($clist as $key => $value) {
-        if ($value['code'] == $code)
-          $rate = number_format($value['rate'], 2, '.', '');
-      }
-
-      return $rate;
-
-    } catch (Exception $e) {
-      if ($this->bitpay_options['useLogging'])
-        $this->error_logger('Error in bitpay_get_rate(): ' . $e->getMessage());
-
-      return 'Error in bitpay_get_rate(): ' . $e->getMessage();
-    }
-  }
-
-  /**
-   * Fallback JSON decoding function in the event you do not have the PHP JSON extension installed and
-   * cannot install it.  This function takes an encoded string and returns an associative array.
-   *
-   * @param string $jsondata
-   * @return array $jsonarray
-   */
-  function bitpay_JSON_decode($jsondata) {
-    $jsondata = trim(stripcslashes(str_ireplace('"', '', str_ireplace('\'', '', $jsondata))));
-    $jsonarray = array();
-    $level = 0;
-
-    if (!is_string($jsondata) || is_null($jsondata) || trim($jsondata) == '' || empty($jsondata))
-      return false;
-
-    if ($jsondata[0] == '[')
-      $jsondata = trim(substr($jsondata, 1, strlen($jsondata)));
-
-    if ($jsondata[0] == '{')
-      $jsondata = trim(substr($jsondata, 1, strlen($jsondata)));
-
-    if (substr($jsondata, strlen($jsondata) - 1, 1) == ']')
-      $jsondata = trim(substr($jsondata, 0, strlen($jsondata) - 1));
-
-    if (substr($jsondata, strlen($jsondata) - 1, 1) == '}')
-      $jsondata = trim(substr($jsondata, 0, strlen($jsondata) - 1));
-
-    $break = false;
-
-    while(!$break) {
-      if (stripos($jsondata,"\t") !== false)
-        $jsondata = str_ireplace("\t", ' ', $jsondata);
-
-      if (stripos($jsondata,"\r") !== false)
-        $jsondata = str_ireplace("\r", '', $jsondata);
-
-      if (stripos($jsondata,"\n") !== false)
-        $jsondata = str_ireplace("\n", '', $jsondata);
-
-      if (stripos($jsondata,' ') !== false)
-        $jsondata = str_ireplace(' ', ' ', $jsondata);
-      else
-        $break = true;
-    }
-
-    $level = 0;
-    $x = 0;
-    $array = false;
-    $object = false;
-
-    while($x < strlen($jsondata)) {
-      $var = '';
-      $val = '';
-
-      while($x < strlen($jsondata) && $jsondata[$x] == ' ')
-        $x++;
-
-      switch($jsondata[$x]) {
-        case '[':
-          $level++;
-          break;
-        case '{':
-          $level++;
-          break;
-      }
-
-      if ($level <= 0) {
-        while($x < strlen($jsondata) && $jsondata[$x] != ':') {
-          if ($jsondata[$x] != ' ') $var .= $jsondata[$x];
-          $x++;
-        }
-
-        $var = trim(stripcslashes(str_ireplace('"', '', $var)));
-
-        while($x < strlen($jsondata) && ($jsondata[$x] == ' ' || $jsondata[$x] == ':'))
-          $x++;
-
-        switch($jsondata[$x]) {
-          case '[':
-            $level++;
-            break;
-          case '{':
-           $level++;
-           break;
-        }
-     }
-
-      if ($level > 0) {
-
-        while($x< strlen($jsondata) && $level > 0) {
-          $val .= $jsondata[$x];
-          $x++;
-
-          switch($jsondata[$x]) {
-            case '[':
-              $level++;
-              break;
-            case '{':
-              $level++;
-              break;
-            case ']':
-              $level--;
-              break;
-            case '}':
-              $level--;
-              break;
-          }
-        }
-
-        if ($jsondata[$x] == ']' || $jsondata[$x] == '}')
-          $val .= $jsondata[$x];
-
-        $val = trim(stripcslashes(str_ireplace('"', '', $val)));
-
-        while($x < strlen($jsondata) && ($jsondata[$x] == ' ' || $jsondata[$x] == ',' || $jsondata[$x] == ']' || $jsondata[$x] == '}'))
-          $x++;
-
-      } else {
-
-        while($x < strlen($jsondata) && $jsondata[$x] != ',') {
-          $val .= $jsondata[$x];
-          $x++;
-        }
-
-        $val = trim(stripcslashes(str_ireplace('"', '', $val)));
-
-        while($x < strlen($jsondata) && ($jsondata[$x] == ' ' || $jsondata[$x] == ','))
-          $x++;
-      }
-
-      $jsonarray[$var] = $val;
-
-      if ($level < 0) $level = 0;
-    }
-
-    return $jsonarray;
-
-  }
-
-  /**
-   * Fallback JSON encoding function in the event you do not have the PHP JSON extension installed and
-   * cannot install it.  This function takes data in various forms and returns a JSON encoded string.
-   *
-   * @param mixed $data
-   * @return string $jsondata
-   */
-  function bitpay_JSON_encode($data) {
-    if (is_array($data)) {
-      $jsondata = '{';
-
-      foreach($data as $key => $value) {
-        $jsondata .= '"' . $key . '": ';
-
-        if (is_array($value))
-          $jsondata .= $this->bitpay_JSON_encode($value) . ', ';
-
-        if (is_numeric($value))
-          $jsondata .= $value . ', ';
-
-        if (is_string($value))
-          $jsondata .= '"' . $value . '", ';
-
-        if (is_bool($value)) {
-          if ($value)
-            $jsondata .= 'true, ';
-          else
-            $jsondata .= 'false, ';
-        }
-
-        if (is_null($value))
-          $jsondata .= 'null, ';
-      }
-
-      $jsondata = substr($jsondata, 0, strlen($jsondata) - 2);
-      $jsondata .= '}';
-
-    } else {
-      $jsondata = '{"' . $data . '"}';
-    }
-
-    return $jsondata;
-  }
-
-  /**
-   * Fallback cURL error string function in the event you do not have PHP >= 5.5.0 installed.  These cURL
-   * error codes and descriptions were retrieved from the official libcurl error documentation.  See:
-   * http://curl.haxx.se/libcurl/c/libcurl-errors.html
-   *
-   * @param integer $errorno
-   * @return string $error_description
-   */
-  function bitpay_curl_Strerror($errorno) {
-    $error_description = '';
-
-    if (!is_int($errorno) || is_null($errorno) || empty($errorno))
-      return 'Error in bitpay_curl_Strerror(): No error number integer passed to function. Usage: bitpay_curl_Strerror($errorno)';
-
-    switch($errorno) {
-      case 0:
-        /*
-         * CURLE_OK (0)
-         */
-        $error_description = 'CURLE_OK: All fine. Proceed as usual.';
-        break;
-      case 1:
-        /*
-         * CURLE_UNSUPPORTED_PROTOCOL (1)
-         */
-        $error_description = 'CURLE_UNSUPPORTED_PROTOCOL: The URL you passed to libcurl used a protocol that this libcurl does not support. The support might be a compile-time option that you didn\'t use, it can be a misspelled protocol string or just a protocol libcurl has no code for.';
-        break;
-      case 2:
-        /*
-         * CURLE_FAILED_INIT (2)
-         */
-        $error_description = 'CURLE_FAILED_INIT: Very early initialization code failed. This is likely to be an internal error or problem, or a resource problem where something fundamental couldn\'t get done at init time.';
-        break;
-      case 3:
-        /*
-         * CURLE_URL_MALFORMAT (3)
-         */
-        $error_description = 'CURLE_URL_MALFORMAT: The URL was not properly formatted.';
-        break;
-      case 4:
-        /*
-         * CURLE_NOT_BUILT_IN (4)
-         */
-        $error_description = 'CURLE_NOT_BUILT_IN: A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. This means that a feature or option was not enabled or explicitly disabled when libcurl was built and in order to get it to function you have to get a rebuilt libcurl.';
-        break;
-      case 5:
-        /*
-         * CURLE_COULDNT_RESOLVE_PROXY (5)
-         */
-        $error_description = 'CURLE_COULDNT_RESOLVE_PROXY: Couldn\'t resolve proxy. The given proxy host could not be resolved.';
-        break;
-      case 6:
-        /*
-         * CURLE_COULDNT_RESOLVE_HOST (6)
-         */
-        $error_description = 'CURLE_COULDNT_RESOLVE_HOST: Couldn\'t resolve host. The given remote host was not resolved.';
-        break;
-      case 7:
-        /*
-         * CURLE_COULDNT_CONNECT (7)
-         */
-        $error_description = 'CURLE_COULDNT_CONNECT: Failed to connect() to host or proxy.';
-        break;
-      case 8:
-        /*
-         * CURLE_FTP_WEIRD_SERVER_REPLY (8)
-         */
-        $error_description = 'CURLE_FTP_WEIRD_SERVER_REPLY: After connecting to a FTP server, libcurl expects to get a certain reply back. This error code implies that it got a strange or bad reply. The given remote server is probably not an OK FTP server.';
-        break;
-      case 9:
-        /*
-         * CURLE_REMOTE_ACCESS_DENIED (9)
-         */
-        $error_description = 'CURLE_REMOTE_ACCESS_DENIED: We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory.';
-        break;
-      case 10:
-        /*
-         * CURLE_FTP_ACCEPT_FAILED (10)
-         */
-        $error_description = 'CURLE_FTP_ACCEPT_FAILED: While waiting for the server to connect back when an active FTP session is used, an error code was sent over the control connection or similar.';
-        break;
-      case 11:
-        /*
-         * CURLE_FTP_WEIRD_PASS_REPLY (11)
-         */
-        $error_description = 'CURLE_FTP_WEIRD_PASS_REPLY: After having sent the FTP password to the server, libcurl expects a proper reply. This error code indicates that an unexpected code was returned.';
-        break;
-      case 12:
-        /*
-         * CURLE_FTP_ACCEPT_TIMEOUT (12)
-         */
-        $error_description = 'CURLE_FTP_ACCEPT_TIMEOUT: During an active FTP session while waiting for the server to connect, the CURLOPT_ACCEPTTIMOUT_MS(3) (or the internal default) timeout expired.';
-        break;
-      case 13:
-        /*
-         * CURLE_FTP_WEIRD_PASV_REPLY (13)
-         */
-        $error_description = 'CURLE_FTP_WEIRD_PASV_REPLY: libcurl failed to get a sensible result back from the server as a response to either a PASV or a EPSV command. The server is flawed.';
-        break;
-      case 14:
-        /*
-         * CURLE_FTP_WEIRD_227_FORMAT (14)
-         */
-        $error_description = 'CURLE_FTP_WEIRD_227_FORMAT: FTP servers return a 227-line as a response to a PASV command. If libcurl fails to parse that line, this return code is passed back.';
-        break;
-      case 15:
-        /*
-         * CURLE_FTP_CANT_GET_HOST (15)
-         */
-        $error_description = 'CURLE_FTP_CANT_GET_HOST: An internal failure to lookup the host used for the new connection.';
-        break;
-      case 17:
-        /*
-         * CURLE_FTP_COULDNT_SET_TYPE (17)
-         */
-        $error_description = 'CURLE_FTP_COULDNT_SET_TYPE: Received an error when trying to set the transfer mode to binary or ASCII.';
-        break;
-      case 18:
-        /*
-         * CURLE_PARTIAL_FILE (18)
-         */
-        $error_description = 'CURLE_PARTIAL_FILE: A file transfer was shorter or larger than expected. This happens when the server first reports an expected transfer size, and then delivers data that doesn\'t match the previously given size.';
-        break;
-      case 19:
-        /*
-         * CURLE_FTP_COULDNT_RETR_FILE (19)
-         */
-        $error_description = 'CURLE_FTP_COULDNT_RETR_FILE: This was either a weird reply to a \'RETR\' command or a zero byte transfer complete.';
-        break;
-      case 21:
-        /*
-         * CURLE_QUOTE_ERROR (21)
-         */
-        $error_description = 'CURLE_QUOTE_ERROR: When sending custom "QUOTE" commands to the remote server, one of the commands returned an error code that was 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command.';
-        break;
-      case 22:
-        /*
-         * CURLE_HTTP_RETURNED_ERROR (22)
-         */
-        $error_description = 'CURLE_HTTP_RETURNED_ERROR: This is returned if CURLOPT_FAILONERROR is set TRUE and the HTTP server returns an error code that is >= 400.';
-        break;
-      case 23:
-        /*
-         * CURLE_WRITE_ERROR (23)
-         */
-        $error_description = 'CURLE_WRITE_ERROR: An error occurred when writing received data to a local file, or an error was returned to libcurl from a write callback.';
-        break;
-      case 25:
-        /*
-         * CURLE_UPLOAD_FAILED (25)
-         */
-        $error_description = 'CURLE_UPLOAD_FAILED: Failed starting the upload. For FTP, the server typically denied the STOR command. The error buffer usually contains the server\'s explanation for this.';
-        break;
-      case 26:
-        /*
-         * CURLE_READ_ERROR (26)
-         */
-        $error_description = 'CURLE_READ_ERROR: There was a problem reading a local file or an error returned by the read callback.';
-        break;
-      case 27:
-        /*
-         * CURLE_OUT_OF_MEMORY (27)
-         */
-        $error_description = 'CURLE_OUT_OF_MEMORY: A memory allocation request failed. This is serious badness and things are severely screwed up if this ever occurs.';
-        break;
-      case 28:
-        /*
-         * CURLE_OPERATION_TIMEDOUT (28)
-         */
-        $error_description = 'CURLE_OPERATION_TIMEDOUT: Operation timeout. The specified time-out period was reached according to the conditions.';
-        break;
-      case 30:
-        /*
-         * CURLE_FTP_PORT_FAILED (30)
-         */
-        $error_description = 'CURLE_FTP_PORT_FAILED: The FTP PORT command returned error. This mostly happens when you haven\'t specified a good enough address for libcurl to use. See CURLOPT_FTPPORT.';
-        break;
-      case 31:
-        /*
-         * CURLE_FTP_COULDNT_USE_REST (31)
-         */
-        $error_description = 'CURLE_FTP_COULDNT_USE_REST: The FTP REST command returned error. This should never happen if the server is sane.';
-        break;
-      case 33:
-        /*
-         * CURLE_RANGE_ERROR (33)
-         */
-        $error_description = 'CURLE_RANGE_ERROR: The server does not support or accept range requests.';
-        break;
-      case 34:
-        /*
-         * CURLE_HTTP_POST_ERROR (34)
-         */
-        $error_description = 'CURLE_HTTP_POST_ERROR: This is an odd error that mainly occurs due to internal confusion.';
-        break;
-      case 35:
-        /*
-         * CURLE_SSL_CONNECT_ERROR (35)
-         */
-        $error_description = 'CURLE_SSL_CONNECT_ERROR: A problem occurred somewhere in the SSL/TLS handshake. You really want the error buffer and read the message there as it pinpoints the problem slightly more. Could be certificates (file formats, paths, permissions), passwords, and others.';
-        break;
-      case 36:
-        /*
-         * CURLE_BAD_DOWNLOAD_RESUME (36)
-         */
-        $error_description = 'CURLE_BAD_DOWNLOAD_RESUME: The download could not be resumed because the specified offset was out of the file boundary.';
-        break;
-      case 37:
-        /*
-         * CURLE_FILE_COULDNT_READ_FILE (37)
-         */
-        $error_description = 'CURLE_FILE_COULDNT_READ_FILE: A file given with FILE:// couldn\'t be opened. Most likely because the file path doesn\'t identify an existing file. Did you check file permissions?';
-        break;
-      case 38:
-        /*
-         * CURLE_LDAP_CANNOT_BIND (38)
-         */
-        $error_description = 'CURLE_LDAP_CANNOT_BIND: LDAP cannot bind. LDAP bind operation failed.';
-        break;
-      case 39:
-        /*
-         * CURLE_LDAP_SEARCH_FAILED (39)
-         */
-        $error_description = 'CURLE_LDAP_SEARCH_FAILED: LDAP search failed.';
-        break;
-      case 41:
-        /*
-         * CURLE_FUNCTION_NOT_FOUND (41)
-         */
-        $error_description = 'CURLE_FUNCTION_NOT_FOUND: Function not found. A required zlib function was not found.';
-        break;
-      case 42:
-        /*
-         * CURLE_ABORTED_BY_CALLBACK (42)
-         */
-        $error_description = 'CURLE_ABORTED_BY_CALLBACK: Aborted by callback. A callback returned "abort" to libcurl.';
-        break;
-      case 43:
-        /*
-         * CURLE_BAD_FUNCTION_ARGUMENT (43)
-         */
-        $error_description = 'CURLE_BAD_FUNCTION_ARGUMENT: Internal error. A function was called with a bad parameter.';
-        break;
-      case 45:
-        /*
-         * CURLE_INTERFACE_FAILED (45)
-         */
-        $error_description = 'CURLE_INTERFACE_FAILED: Interface error. A specified outgoing interface could not be used. Set which interface to use for outgoing connections\' source IP address with CURLOPT_INTERFACE.';
-        break;
-      case 47:
-        /*
-         * CURLE_TOO_MANY_REDIRECTS (47)
-         */
-        $error_description = 'CURLE_TOO_MANY_REDIRECTS: Too many redirects. When following redirects, libcurl hit the maximum amount. Set your limit with CURLOPT_MAXREDIRS.';
-        break;
-      case 48:
-        /*
-         * CURLE_UNKNOWN_OPTION (48)
-         */
-        $error_description = 'CURLE_UNKNOWN_OPTION: An option passed to libcurl is not recognized/known. Refer to the appropriate documentation. This is most likely a problem in the program that uses libcurl. The error buffer might contain more specific information about which exact option it concerns.';
-        break;
-      case 49:
-        /*
-         * CURLE_TELNET_OPTION_SYNTAX (49)
-         */
-        $error_description = 'CURLE_TELNET_OPTION_SYNTAX: A telnet option string was Illegally formatted.';
-        break;
-      case 51:
-        /*
-         * CURLE_PEER_FAILED_VERIFICATION (51)
-         */
-        $error_description = 'CURLE_PEER_FAILED_VERIFICATION: The remote server\'s SSL certificate or SSH md5 fingerprint was deemed not OK.';
-        break;
-      case 52:
-        /*
-         * CURLE_GOT_NOTHING (52)
-         */
-        $error_description = 'CURLE_GOT_NOTHING: Nothing was returned from the server, and under the circumstances, getting nothing is considered an error.';
-        break;
-      case 53:
-        /*
-         * CURLE_SSL_ENGINE_NOTFOUND (53)
-         */
-        $error_description = 'CURLE_SSL_ENGINE_NOTFOUND: The specified crypto engine wasn\'t found.';
-        break;
-      case 54:
-        /*
-         * CURLE_SSL_ENGINE_SETFAILED (54)
-         */
-        $error_description = 'CURLE_SSL_ENGINE_SETFAILED: Failed setting the selected SSL crypto engine as default!';
-        break;
-      case 55:
-        /*
-         * CURLE_SEND_ERROR (55)
-         */
-        $error_description = 'CURLE_SEND_ERROR: Failed sending network data.';
-        break;
-      case 56:
-        /*
-         * CURLE_RECV_ERROR (56)
-         */
-        $error_description = 'CURLE_RECV_ERROR: Failure with receiving network data.';
-        break;
-      case 58:
-        /*
-         * CURLE_SSL_CERTPROBLEM (58)
-         */
-        $error_description = 'CURLE_SSL_CERTPROBLEM: Problem with the local client certificate.';
-        break;
-      case 59:
-        /*
-         * CURLE_SSL_CIPHER (59)
-         */
-        $error_description = 'CURLE_SSL_CIPHER: Couldn\'t use specified cipher.';
-        break;
-      case 60:
-        /*
-         * CURLE_SSL_CACERT (60)
-         */
-        $error_description = 'CURLE_SSL_CACERT: Peer certificate cannot be authenticated with known CA certificates.';
-        break;
-      case 61:
-        /*
-         * CURLE_BAD_CONTENT_ENCODING (61)
-         */
-        $error_description = 'CURLE_BAD_CONTENT_ENCODING: Unrecognized transfer encoding.';
-        break;
-      case 62:
-        /*
-         * CURLE_LDAP_INVALID_URL (62)
-         */
-        $error_description = 'CURLE_LDAP_INVALID_URL: Invalid LDAP URL.';
-        break;
-      case 63:
-        /*
-         * CURLE_FILESIZE_EXCEEDED (63)
-         */
-        $error_description = 'CURLE_FILESIZE_EXCEEDED: Maximum file size exceeded.';
-        break;
-      case 64:
-        /*
-         * CURLE_USE_SSL_FAILED (64)
-         */
-        $error_description = 'CURLE_USE_SSL_FAILED: Requested FTP SSL level failed.';
-        break;
-      case 65:
-        /*
-         * CURLE_SEND_FAIL_REWIND (65)
-         */
-        $error_description = 'CURLE_SEND_FAIL_REWIND: When doing a send operation curl had to rewind the data to retransmit, but the rewinding operation failed.';
-        break;
-      case 66:
-        /*
-         * CURLE_SSL_ENGINE_INITFAILED (66)
-         */
-        $error_description = 'CURLE_SSL_ENGINE_INITFAILED: Initiating the SSL Engine failed.';
-        break;
-      case 67:
-        /*
-         * CURLE_LOGIN_DENIED (67)
-         */
-        $error_description = 'CURLE_LOGIN_DENIED: The remote server denied curl to login (Added in 7.13.1)';
-        break;
-      case 68:
-        /*
-         * CURLE_TFTP_NOTFOUND (68)
-         */
-        $error_description = 'CURLE_TFTP_NOTFOUND: File not found on TFTP server.';
-        break;
-      case 69:
-        /*
-         * CURLE_TFTP_PERM (69)
-         */
-        $error_description = 'CURLE_TFTP_PERM: Permission problem on TFTP server.';
-        break;
-      case 70:
-        /*
-         * CURLE_REMOTE_DISK_FULL (70)
-         */
-        $error_description = 'CURLE_REMOTE_DISK_FULL: Out of disk space on the server.';
-        break;
-      case 71:
-        /*
-         * CURLE_TFTP_ILLEGAL (71)
-         */
-        $error_description = 'CURLE_TFTP_ILLEGAL: Illegal TFTP operation.';
-        break;
-      case 72:
-        /*
-         * CURLE_TFTP_UNKNOWNID (72)
-         */
-        $error_description = 'CURLE_TFTP_UNKNOWNID: Unknown TFTP transfer ID.';
-        break;
-      case 73:
-        /*
-         * CURLE_REMOTE_FILE_EXISTS (73)
-         */
-        $error_description = 'CURLE_REMOTE_FILE_EXISTS: File already exists and will not be overwritten.';
-        break;
-      case 74:
-        /*
-         * CURLE_TFTP_NOSUCHUSER (74)
-         */
-        $error_description = 'CURLE_TFTP_NOSUCHUSER: This error should never be returned by a properly functioning TFTP server.';
-        break;
-      case 75:
-        /*
-         * CURLE_CONV_FAILED (75)
-         */
-        $error_description = 'CURLE_CONV_FAILED: Character conversion failed.';
-        break;
-      case 76:
-        /*
-         * CURLE_CONV_REQD (76)
-         */
-        $error_description = 'CURLE_CONV_REQD: Caller must register conversion callbacks.';
-        break;
-      case 77:
-        /*
-         * CURLE_SSL_CACERT_BADFILE (77)
-         */
-        $error_description = 'CURLE_SSL_CACERT_BADFILE: Problem with reading the SSL CA cert (path? access rights?)';
-        break;
-      case 78:
-        /*
-         * CURLE_REMOTE_FILE_NOT_FOUND (78)
-         */
-        $error_description = 'CURLE_REMOTE_FILE_NOT_FOUND: The resource referenced in the URL does not exist.';
-        break;
-      case 79:
-        /*
-         * CURLE_SSH (79)
-         */
-        $error_description = 'CURLE_SSH: An unspecified error occurred during the SSH session.';
-        break;
-      case 80:
-        /*
-         * CURLE_SSL_SHUTDOWN_FAILED (80)
-         */
-        $error_description = 'CURLE_SSL_SHUTDOWN_FAILED: Failed to shut down the SSL connection.';
-        break;
-      case 81:
-        /*
-         * CURLE_AGAIN (81)
-         */
-        $error_description = 'CURLE_AGAIN: Socket is not ready for send/recv wait till it\'s ready and try again. This return code is only returned from curl_easy_recv and curl_easy_send (Added in 7.18.2)';
-        break;
-      case 82:
-        /*
-         * CURLE_SSL_CRL_BADFILE (82)
-         */
-        $error_description = 'CURLE_SSL_CRL_BADFILE: Failed to load CRL file (Added in 7.19.0)';
-        break;
-      case 83:
-        /*
-         * CURLE_SSL_ISSUER_ERROR (83)
-         */
-        $error_description = 'CURLE_SSL_ISSUER_ERROR: Issuer check failed (Added in 7.19.0)';
-        break;
-      case 84:
-        /*
-         * CURLE_FTP_PRET_FAILED (84)
-         */
-        $error_description = 'CURLE_FTP_PRET_FAILED: The FTP server does not understand the PRET command at all or does not support the given argument. Be careful when using CURLOPT_CUSTOMREQUEST, a custom LIST command will be sent with PRET CMD before PASV as well. (Added in 7.20.0)';
-        break;
-      case 85:
-        /*
-         * CURLE_RTSP_CSEQ_ERROR (85)
-         */
-        $error_description = 'CURLE_RTSP_CSEQ_ERROR: Mismatch of RTSP CSeq numbers.';
-        break;
-      case 86:
-        /*
-         * CURLE_RTSP_SESSION_ERROR (86)
-         */
-        $error_description = 'CURLE_RTSP_SESSION_ERROR: Mismatch of RTSP Session Identifiers.';
-        break;
-      case 87:
-        /*
-         * CURLE_FTP_BAD_FILE_LIST (87)
-         */
-        $error_description = 'CURLE_FTP_BAD_FILE_LIST: Unable to parse FTP file list (during FTP wildcard downloading).';
-        break;
-      case 88:
-        /*
-         * CURLE_CHUNK_FAILED (88)
-         */
-        $error_description = 'CURLE_CHUNK_FAILED: Chunk callback reported error.';
-        break;
-      case 89:
-        /*
-         * CURLE_NO_CONNECTION_AVAILABLE (89) - Added for completeness.
-         */
-        $error_description = 'CURLE_NO_CONNECTION_AVAILABLE: (For internal use only, will never be returned by libcurl) No connection available, the session will be queued. (added in 7.30.0)';
-        break;
-      default:
-        $error_description = 'UNKNOWN CURL ERROR NUMBER: This error code is not mapped to any known error.  Possibly a system error?';
-        break;
-    }
-
-    return $error_description;
-  }
-
-}
diff --git a/eclipse.org-common/classes/friends/payment.class.php b/eclipse.org-common/classes/friends/payment.class.php
index a42c8fe..5ea5979 100644
--- a/eclipse.org-common/classes/friends/payment.class.php
+++ b/eclipse.org-common/classes/friends/payment.class.php
@@ -192,7 +192,7 @@
     else {
      $EvtLog->setPK1("Unknown");
     }
-    $ip = $_SERVER['REMOTE_ADDR'];
+    $ip = $this->App->getRemoteIPAddress();
     $EvtLog->setPK2($ip);
     $EvtLog->setLogAction($action);
     if ($this->donor_email) {
@@ -269,4 +269,3 @@
 }
 
 require_once("gateway/paypal.class.php");
-require_once("gateway/bitpay.class.php");
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/paymentGateway.class.php b/eclipse.org-common/classes/friends/paymentGateway.class.php
index 93378a7..921a535 100644
--- a/eclipse.org-common/classes/friends/paymentGateway.class.php
+++ b/eclipse.org-common/classes/friends/paymentGateway.class.php
@@ -18,7 +18,7 @@
  * Base class for gateway class
  *
  * We currently have two supported gateway classes.
- * They are paypal or bitpay.
+ * They are paypal.
  *
  * @author chrisguindon
  *
@@ -91,7 +91,7 @@
   /**
    * Type of gateway
    *
-   * This should probably set to bitpay or paypal
+   * This should probably set to paypal
    * for now.
    */
   protected $gateway_type = "";
@@ -140,20 +140,23 @@
   }
 
   /**
-   * Set a client message for returning bitpay donation
+   * Maintenance for friends_process table
    */
-  public function get_gateway_bitpay_thank_you() {
-    $bitpay_return = $this->App->getHTTPParameter('bitpay_return', 'get');
-    if ($bitpay_return == 'donation') {
-      setcookie("thankyou_page[eclipse_donation]", TRUE, time() + (3600 * 24 * 360 * 10), '/', $this->_get_prefix_cookie());
-      $this->set_client_message( '<strong>Thank you for your donation!</strong>', 'success');
+  public function maintenance(){
+    $table = 'friends_process';
+    if ($this->_get_debug_mode()) {
+      $table = 'testing_' . $table;
     }
+    $sql = 'DELETE from ' . $table .' WHERE timestamp  <= (NOW() - INTERVAL 3 MONTH)
+    AND status != "COMPLETED" AND status != "CONFIRMED" ORDER BY timestamp DESC';
+    return $this->App->eclipse_sql($sql);
   }
 
   /**
    * Store form values from donation form or process script
    */
   public function update_friends_process_table($update = FALSE) {
+    $this->maintenance();
     $fields = array(
       'id_unique' => $this->Donation->get_donation_random_invoice_id(),
       'uid' => $this->Donation->Donor->get_donor_uid(),
@@ -168,7 +171,11 @@
       'is_anonymous' => $this->Donation->get_donation_is_anonymous(),
       'redirect_url' => $this->get_gateway_redirect(),
       'status' => $this->Donation->get_donation_status(),
-      'email_paypal' => $this->Donation->Donor->get_donor_paypal_email()
+      'email_paypal' => $this->Donation->Donor->get_donor_paypal_email(),
+      'landing_page' => $this->Donation->get_donation_landing_page(),
+      'file_id' => $this->Donation->get_donation_file_id(),
+      'scope' => $this->Donation->get_donation_scope(),
+      'campaign' => $this->Donation->get_donation_campaign(),
     );
 
     if ($update) {
@@ -184,7 +191,11 @@
       'email',
       'email_paypal',
       'amount',
-      'domain'
+      'domain',
+      'landing_page',
+      'scope',
+      'campaign',
+      'file_id'
     );
 
     $sql = $this->_sql_on_duplicate_update('friends_process', $fields, $possible_null_field);
@@ -200,6 +211,10 @@
     $this->Donation->set_donation_subscription($this->App->getHTTPParameter('subscription'));
     $this->Donation->set_donation_is_anonymous($this->App->getHTTPParameter('is_anonymous'));
     $this->Donation->set_donation_status('new_donation_form');
+    $this->Donation->set_donation_landing_page($this->App->getHTTPParameter('landing_page'));
+    $this->Donation->set_donation_file_id($this->App->getHTTPParameter('file_id'));
+    $this->Donation->set_donation_scope($this->App->getHTTPParameter('scope'));
+    $this->Donation->set_donation_campaign($this->App->getHTTPParameter('campaign'));
     $this->_set_gateway_redirect();
     $this->update_friends_process_table();
   }
@@ -357,7 +372,7 @@
    * @param string $gateway_type
    */
   protected function _set_gateway_type($gateway_type = NULL){
-    $haystack = array('bitpay', 'paypal');
+    $haystack = array('paypal');
     if (in_array($gateway_type, $haystack)) {
       $this->gateway_type = $gateway_type;
       $this->Donation->set_donation_currency($gateway_type);
diff --git a/eclipse.org-common/classes/friends/tpl/bitpay-process.tpl.php b/eclipse.org-common/classes/friends/tpl/bitpay-process.tpl.php
deleted file mode 100644
index 08b78ed..0000000
--- a/eclipse.org-common/classes/friends/tpl/bitpay-process.tpl.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-
-$amount = $this->Donation->get_donation_amount();
-if (empty($this->Donation->Donor->donor_email) && $amount >= 35) {
-  $message = '<strong>Please note:</strong> You have not entered your email address in the previous form.
-    Please provide your email address before proceeding to bitpay if you would like to receive your
-    <a href="/donate/benefits.php" target="_blank" title="Friend of Eclipse Benefits">
-    Friend of Eclipse Benefits</a>.<br/><br/>
-    <div class="form-group">
-      <label>Email address:</label><br/>
-      <input type="text" name="buyerEmail" value="" />
-    </div>';
-  $this->set_client_message($message, 'warning');
-}
-
-?>
-<form class="bitpay-donate" action="<?php print $this->_get_gateway_url();?>" method="post">
-  <?php print $this->get_client_message();?>
-  <h1>Please confirm your donation</h1>
-  <?php if (!empty($this->Donation->Donor->donor_first_name) || !empty($this->Donation->Donor->donor_last_name)): ?>
-    <div class="form-group col-xs-12">
-      <label>Name:</label><br/>
-      <?php print $this->Donation->Donor->donor_first_name;?> <?php print $this->Donation->Donor->donor_last_name;?>
-    </div>
-     <input type="hidden" name="buyerName" value="<?php print $this->Donation->Donor->get_donor_full_name();?>" />
-  <?php endif;?>
-
-  <?php if (!empty($this->Donation->Donor->donor_email)): ?>
-    <div class="form-group  col-xs-12">
-      <label>Email address:</label><br/>
-      <?php print $this->Donation->Donor->donor_email;?>
-      <input type="hidden" name="buyerEmail" value="<?php print $this->Donation->Donor->donor_email;?>" />
-    </div>
-  <?php endif;?>
-
-  <div class="form-group  col-xs-12">
-    <label>Donation Amount:</label><br/>
-    $<?php print $this->Donation->donation_amount;?> USD
-  </div>
-
-  <div class="form-group col-xs-12">
-    <label>Visibility:</label><br/>
-    <?php print $this->Donation->get_donation_is_anonymous_string();?>
-  </div>
-
-  <?php if (!empty($this->Donation->message)): ?>
-    <div class="form-group col-xs-24">
-      <label>Comments:</label><br/>
-      <p><?php print $this->Donation->message;?></p>
-    </div>
-  <?php endif;?>
-
-  <div class="form-group col-xs-24 clearix">
-    <input type="hidden" name="action"  value="checkout">
-    <input type="hidden" name="notificationType" value="json" />
-    <input type="hidden" name="price" value="<?php print $this->Donation->get_donation_amount();?>"/>
-    <input type="hidden" name="currency" value="USD"/>
-    <input type="hidden" name="posData" value="<?php print $this->Donation->get_donation_random_invoice_id();?>" />
-    <input type="hidden" name="data" value="<?php print $this->_get_bitpay_data();?>">
-    <button type="submit" name="submit" class="btn btn-warning">Donate with bitpay.com</button>
-  </div>
-</form>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/tpl/displayfriend-credit.tpl.php b/eclipse.org-common/classes/friends/tpl/displayfriend-credit.tpl.php
deleted file mode 100644
index 700799e..0000000
--- a/eclipse.org-common/classes/friends/tpl/displayfriend-credit.tpl.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-<div class="row friends-image">
-  <?php foreach ($results as $r) :?>
-  <div class="col-sm-12">
-    <div class="row">
-      <div class="col-xs-8">
-        <img typeof="foaf:Image" src="<?php print $this->getGravatarURL($r['mail']);?>" alt="<?php print $r['name'];?>" title="<?php print $r['name'];?>" />
-      </div>
-      <div class="col-xs-16">
-        <p><strong><?php print $r['name'];?></strong></p>
-      </div>
-    </div>
-  </div>
-  <?php endforeach;?>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/tpl/displayfriend-default.tpl.php b/eclipse.org-common/classes/friends/tpl/displayfriend-default.tpl.php
deleted file mode 100644
index f319051..0000000
--- a/eclipse.org-common/classes/friends/tpl/displayfriend-default.tpl.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-<div class="row friend-images">
-  <?php foreach ($results as $r): ?>
-  <div class="col-md-6 col-sm-8 col-xs-12">
-    <div class="user-picture">
-      <img class="col-xm-24" typeof="foaf:Image" src="<?php print $this->getGravatarURL($r['mail']);?>" alt="<?php print $r['name'];?>" title="<?php print $r['name'];?>" />
-      <span class="col-xs-24 donor-name"><?php print $r['name'];?></span>
-    </div>
-  </div>
-  <?php endforeach;?>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/tpl/displayfriend-four-columns.tpl.php b/eclipse.org-common/classes/friends/tpl/displayfriend-four-columns.tpl.php
deleted file mode 100644
index e1c95ca..0000000
--- a/eclipse.org-common/classes/friends/tpl/displayfriend-four-columns.tpl.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<?php foreach ($results as $r) :?>
-  <div class="col-md-6 col-sm-12">
-    <?php foreach ($r as $col) :?>
-    <p><?php print $col['name'];?></p>
-    <?php endforeach;?>
-  </div>
-<?php endforeach;?>
diff --git a/eclipse.org-common/classes/friends/tpl/donate_ad.tpl.php b/eclipse.org-common/classes/friends/tpl/donate_ad.tpl.php
deleted file mode 100644
index 00d1539..0000000
--- a/eclipse.org-common/classes/friends/tpl/donate_ad.tpl.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2016 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Eric Poirier (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/classes/friends/payment.class.php");
-$Paypal = new Paypal();
-?>
-
-<div class="donate-ad">
-  <div class="container">
-    <i class="fa fa-times btn-donate-close" aria-hidden="true"></i>
-    <div class="row">
-      <div class="col-sm-14 donate-text">
-        <?php print $banner_content['title']; ?>
-        <?php print $banner_content['text']; ?>
-        <?php print $banner_content['thankyou']; ?>
-
-        <ul class="list-inline">
-          <li><a class="underlined-link" href="mailto:donate@eclipse.org?subject=Donation Problem">Problems donating?</a></li>
-          <li><a class="underlined-link" href="/donate/faq.php" target="_blank">Donation FAQs</a></li>
-        </ul>
-      </div>
-      <div class="col-sm-10 text-center donate-form">
-
-        <form id="donation_default_eclipse_form" action="<?php print $Paypal->get_gateway_process_url();?>?utm_source=eclipse.org&utm_medium=donate_program&utm_content=donate-banner&utm_campaign=eclipse_org_<?php print $banner_content['campaign']; ?>" method="POST">
-          <div class="row">
-            <div class="col-sm-24">
-              <ul class="list-inline list-amount">
-                <li><button type="button" class="btn btn-focus btn-square" value="5">$5</button></li>
-                <li><button type="button" class="btn btn-focus btn-square active" value="10">$10</button></li>
-                <li><button type="button" class="btn btn-focus btn-square" value="35">$35</button></li>
-                <li><button type="button" class="btn btn-focus btn-square" value="50">$50</button></li>
-                <li><button type="button" class="btn btn-focus btn-square" value="100">$100</button></li>
-              </ul>
-            </div>
-          </div>
-
-          <div class="row margin-bottom-5">
-            <div class="col-sm-24">
-              <label class="radio-inline"><input type="radio" name="type" value="paypal" checked="checked"> Paypal</label>
-              <label class="radio-inline"><input type="radio" name="type" value="bitpay"> Bitcoin</label>
-            </div>
-          </div>
-
-          <div class="row margin-bottom-5">
-            <div class="col-sm-24">
-              <label class="radio-inline"><input type="radio" name="subscription" id="subscription_default" value="0" checked="checked"> One-time</label>
-              <label class="radio-inline"><input type="radio" name="subscription" value="M"> Monthly</label>
-              <label class="radio-inline"><input type="radio" name="subscription" value="Y"> Yearly</label>
-              </ul>
-            </div>
-          </div>
-
-          <div class="checkbox">
-            <label>
-              <input class="recognition-checkbox" type="checkbox" value="" name="recognition">
-              I want to be listed on the recognition page
-            </label>
-          </div>
-
-          <div class="recognition-fields form-inline margin-bottom-10">
-            <div class="form-group">
-              <input class="form-control" type="text" name="first_name" placeholder="First Name">
-            </div>
-            <div class="form-group">
-              <input class="form-control" type="text" name="last_name" placeholder="Last Name">
-            </div>
-          </div>
-
-          <div class="form-inline margin-bottom-10 donate-submit">
-            <div class="form-group">
-              <div class="input-group">
-                <div class="input-group-addon">$</div>
-                <input class="donate-amount form-control" type="number" name="amount" value="10">
-              </div>
-            </div>
-            <div class="form-group">
-              <input type="submit" value="Donate" class="btn btn-warning">
-            </div>
-          </div>
-
-        </form>
-      </div>
-    </div>
-
-  </div>
-</div>
\ No newline at end of file
diff --git a/eclipse.org-common/classes/friends/tpl/paypal-process.tpl.php b/eclipse.org-common/classes/friends/tpl/paypal-process.tpl.php
deleted file mode 100644
index 33ddc10..0000000
--- a/eclipse.org-common/classes/friends/tpl/paypal-process.tpl.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2015 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
-?>
-
-<h1>Processing donation...</h1>
-<?php print $this->get_client_message();?>
-<p>Please wait while you are being redirected to paypal.com.</p>
-<p><a href="<?php print $this->get_gateway_redirect();?>" class="btn btn-primary">Continue to paypal.com</a></p>
diff --git a/eclipse.org-common/classes/membership/editMembership.class.php b/eclipse.org-common/classes/membership/editMembership.class.php
index 0e136ba..7e99632 100644
--- a/eclipse.org-common/classes/membership/editMembership.class.php
+++ b/eclipse.org-common/classes/membership/editMembership.class.php
@@ -235,12 +235,15 @@
    * */
   public function fetchUserEmail(){
     if ($this->getToken() != "") {
-      return $this->_fetchEmailBasedOnToken();
+      $mail = $this->_fetchEmailBasedOnToken();
     }
-    if($this->Session->isLoggedIn()){
+
+    if(empty($mail) && $this->Session->isLoggedIn()){
       $Friend = $this->Session->getFriend();
-      return $Friend->getEmail();
+      $mail = $Friend->getEmail();
     }
+
+    return !empty($mail) ? $mail : "";
   }
 
   /**
@@ -250,47 +253,51 @@
   public function fetchMemberMaintainers($_users = ""){
     $_email = $this->App->returnQuotedString($this->App->sqlSanitize($this->fetchUserEmail()));
     $_member_id = $this->App->returnQuotedString($this->App->sqlSanitize($this->id));
-    $sql = 'SELECT
-            p.PersonID, p.FName, p.LName, p.EMail, p.Phone,
-            group_concat("",
-            CASE oc.Relation
-               WHEN "MPE" THEN "Membership Page Editor"
-               WHEN "DE"  THEN "Delegate"
-               WHEN "MA"  THEN "Marketing"
-               WHEN "CR"  THEN "Company Representative"
-            END) as Type
-            FROM People as p
-            LEFT JOIN OrganizationContacts as oc
-              ON p.PersonID = oc.PersonID ';
-    if ($_users == EDITMEMBERSHIP_LOGGED_IN_USER) {
-      $sql .= 'WHERE p.EMail = '. $_email;
-    }
-    else {
-      $sql .= 'WHERE p.EMail IN
-                (SELECT
-                  p.Email
-                  FROM OrganizationContacts as oc
-                  LEFT JOIN People as p
-                  ON oc.PersonID = p.PersonID
-                  WHERE OrganizationID = ' . $_member_id . '
-                )';
-    }
-    $sql .= 'AND (oc.Relation = "CR" OR oc.Relation = "MA" OR oc.Relation = "DE" OR oc.Relation = "MPE")
-            AND OrganizationID = ' . $_member_id . '
-            GROUP BY p.PersonID';
-    $result = $this->App->foundation_sql($sql);
+    if (!empty($_member_id)) {
+      $sql = 'SELECT
+              p.PersonID, p.FName, p.LName, p.EMail, p.Phone,
+              group_concat("",
+              CASE oc.Relation
+                 WHEN "MPE" THEN "Membership Page Editor"
+                 WHEN "DE"  THEN "Delegate"
+                 WHEN "MA"  THEN "Marketing"
+                 WHEN "CR"  THEN "Company Representative"
+              END) as Type
+              FROM People as p
+              LEFT JOIN OrganizationContacts as oc
+                ON p.PersonID = oc.PersonID ';
 
-    // Build the array containing the Employees of this Member
-    $_contacts = array();
-    while ($row = mysql_fetch_assoc($result)) {
-      $_contacts[$row['PersonID']]['PersonID'] = $row['PersonID'];
-      $_contacts[$row['PersonID']]['FName'] = $row['FName'];
-      $_contacts[$row['PersonID']]['LName'] = $row['LName'];
-      $_contacts[$row['PersonID']]['EMail'] = $row['EMail'];
-      $_contacts[$row['PersonID']]['Phone'] = ($row['Phone'] != NULL ? $row['Phone'] : 'N/A');
-      $_contacts[$row['PersonID']]['Type'] = ($row['Type'] != NULL ? $row['Type'] : 'N/A');
+      if ($_users == EDITMEMBERSHIP_LOGGED_IN_USER) {
+        $sql .= 'WHERE p.EMail = '. $_email;
+      }
+      else {
+        $sql .= 'WHERE p.EMail IN
+                  (SELECT
+                    p.Email
+                    FROM OrganizationContacts as oc
+                    LEFT JOIN People as p
+                    ON oc.PersonID = p.PersonID
+                    WHERE OrganizationID = ' . $_member_id . '
+                  )';
+      }
+      $sql .= 'AND (oc.Relation = "CR" OR oc.Relation = "MA" OR oc.Relation = "DE" OR oc.Relation = "MPE")
+              AND OrganizationID = ' . $_member_id . '
+              GROUP BY p.PersonID';
+      $result = $this->App->foundation_sql($sql);
+
+      // Build the array containing the Employees of this Member
+      $_contacts = array();
+      while ($row = mysql_fetch_assoc($result)) {
+        $_contacts[$row['PersonID']]['PersonID'] = $row['PersonID'];
+        $_contacts[$row['PersonID']]['FName'] = $row['FName'];
+        $_contacts[$row['PersonID']]['LName'] = $row['LName'];
+        $_contacts[$row['PersonID']]['EMail'] = $row['EMail'];
+        $_contacts[$row['PersonID']]['Phone'] = ($row['Phone'] != NULL ? $row['Phone'] : 'N/A');
+        $_contacts[$row['PersonID']]['Type'] = ($row['Type'] != NULL ? $row['Type'] : 'N/A');
+      }
     }
-    return $_contacts;
+
+    return !empty($_contacts) ? $_contacts : array();
   }
 
   /**
@@ -337,6 +344,101 @@
   }
 
   /**
+   * Is the user a valid maintainer for org?
+   *
+   * @return boolean
+   */
+  public function isMaintainer() {
+    $member_id = $this->id;
+    $email = $this->fetchUserEmail();
+    if (!empty($email) && !empty($member_id)) {
+      $member_id = $this->App->returnQuotedString($this->App->sqlSanitize($member_id));
+      $email = $this->App->returnQuotedString($this->App->sqlSanitize($email));
+
+      $sql = 'SELECT p.EMail FROM OrganizationContacts as oc
+    LEFT JOIN People as p
+    ON oc.PersonID = p.PersonID
+    WHERE oc.OrganizationID = ' . $member_id . '
+    AND p.EMail = ' . $email . '
+    AND (oc.Relation = "CR" OR oc.Relation = "MA" OR oc.Relation = "DE" OR oc.Relation = "MPE")';
+
+      $result = $this->App->foundation_sql($sql);
+
+      while ($row = mysql_fetch_assoc($result)) {
+        $return = TRUE;
+        break;
+      }
+    }
+
+    return !empty($return) ? TRUE : FALSE;
+  }
+
+  /**
+   * Validate token
+   *
+   * @return boolean
+   */
+  public function validateToken() {
+    $member_id = $this->id;
+    $token = $this->getToken();
+    $email = $this->fetchUserEmail();
+    if (!empty($email) && !empty($member_id) && !empty($token)) {
+      $token = $this->App->returnQuotedString($this->App->sqlSanitize($token));
+      $member_id = $this->App->returnQuotedString($this->App->sqlSanitize($member_id));
+      $email = $this->App->returnQuotedString($this->App->sqlSanitize($email));
+      $subnet = $this->App->returnQuotedString($this->App->sqlSanitize($this->App->getSubnet()));
+
+      // Check to see if the token is there and valid
+      $sql = 'SELECT ValidUntil FROM OrganizationTokens WHERE Token = ' . $token
+      . ' and OrganizationID = ' . $member_id
+      . ' and Email = ' . $email
+      . ' and Subnet = ' . $subnet;
+
+      $result = $this->App->eclipse_sql($sql);
+
+      while ($row = mysql_fetch_assoc($result)) {
+        // Check to see if the token has expired
+        $current_time = date('Y-m-d H:i:s');
+        if ($row['ValidUntil'] > $current_time) {
+          $return = TRUE;
+          break;
+        }
+      }
+    }
+
+    return !empty($return) ? TRUE : FALSE;
+  }
+
+  /**
+   * Is logged-in user an admin?
+   *
+   * @return boolean
+   */
+  public function isAdmin(){
+     $admins = array(
+      'pmisingnameu8g' => 'perri.lavergne@eclipse-foundation.org',
+      'zfazli' => 'zahra.fazli@eclipse-foundation.org',
+      'webdev' => 'webdev@eclipse.org',
+      'cwitt' => 'christie.witt@eclipse-foundation.org'
+    );
+
+    $Friend = $this->Session->getFriend();
+    $friend_uid = strtolower($Friend->getUID());
+    $friend_email = strtolower($Friend->getEmail());
+
+    $valid = FALSE;
+     // Is the user an admin?
+    foreach ($admins as $username => $email) {
+      if ($friend_uid === $username && $friend_email === $email) {
+        $valid = TRUE;
+        break;
+      }
+    }
+
+    return !empty($valid) ? TRUE : FALSE;
+  }
+
+  /**
    * Validate the user
    * - Check if the logged in user is a maintainer of the selected Member
    * - Check if the token submitted is valid
@@ -344,53 +446,25 @@
    * @param string
    * */
   public function validateUser(){
-    $email = $this->App->returnQuotedString($this->App->sqlSanitize($this->fetchUserEmail()));
-    $member_id = $this->App->returnQuotedString($this->App->sqlSanitize($this->id));
-    $token = $this->App->returnQuotedString($this->App->sqlSanitize($this->getToken()));
-    $_has_eclipse_account = "";
-    $_is_maintainer = array();
-    $_valid_token = array();
-    $user_verified = FALSE;
 
-    if(!empty($member_id) && !empty($email)){
-      $sql_maintainer = 'SELECT
-                         p.EMail
-                         FROM OrganizationContacts as oc
-                         LEFT JOIN People as p
-                         ON oc.PersonID = p.PersonID
-                         WHERE oc.OrganizationID = '. $member_id .'
-                         AND p.EMail = '. $email .'
-                         AND (oc.Relation = "CR" OR oc.Relation = "MA" OR oc.Relation = "DE" OR oc.Relation = "MPE")';
-      $result_maintainer = $this->App->foundation_sql($sql_maintainer);
+    $valid = FALSE;
 
-      while ($row = mysql_fetch_assoc($result_maintainer)) {
-        $_is_maintainer[] = $row['EMail'];
-        break;
-      }
+    // Is the logged in user an admin?
+    if ($this->isAdmin()) {
+       $valid = TRUE;
     }
 
-    if(!empty($member_id) && !empty($token)){
-      // Check to see if the token is there and valid
-      $sql_token = 'SELECT *
-                    FROM OrganizationTokens
-                    WHERE Token = ' . $token;
-      $result_token = $this->App->eclipse_sql($sql_token);
-
-      while ($row = mysql_fetch_assoc($result_token)) {
-        // Check to see if the token has expired
-        $current_time = date('Y-m-d H:i:s');
-        if($row['ValidUntil'] > $current_time && $row['Subnet'] == $this->App->getSubnet()){
-          $_valid_token[] = $row['Token'];
-          break;
-        }
-      }
+    // Is the user a maintainer?
+    if (!$valid && $this->isMaintainer()) {
+      $valid = TRUE;
     }
 
-    // Is a Maintainer AND has an Eclipse Account
-    if(!empty($_is_maintainer) || !empty($_valid_token)){
-      $user_verified = TRUE;
+    // Is this a valid token for the user?
+    if (!$valid && $this->validateToken()) {
+      $valid = TRUE;
     }
-    return $user_verified;
+
+    return !empty($valid) ? TRUE : FALSE;
   }
 
   /**
@@ -742,9 +816,11 @@
       case IMAGETYPE_GIF:  $image = imagecreatefromgif($_tmp_name); break;
       case IMAGETYPE_JPEG:  $image = imagecreatefromjpeg($_tmp_name); break;
       case IMAGETYPE_PNG:
+        imagealphablending($logo_resize, FALSE);
+        imagesavealpha($logo_resize, TRUE);
         $image = imagecreatefrompng($_tmp_name);
-        $white = imagecolorallocate($logo_resize, 255, 255, 255);
-        imagefilledrectangle($logo_resize, 0, 0, $new_width, $new_height, $white);
+        $transparent = imagecolorallocatealpha($logo_resize, 255, 255, 255, 127);
+        imagefilledrectangle($logo_resize, 0, 0, $new_width, $new_height, $transparent);
         break;
     }
     imagecopyresampled($logo_resize, $image, 0, 0, 0, 0, $new_width, $new_height, $_width, $_height);
diff --git a/eclipse.org-common/classes/membership/membership.class.php b/eclipse.org-common/classes/membership/membership.class.php
index d63e6b1..155e466 100644
--- a/eclipse.org-common/classes/membership/membership.class.php
+++ b/eclipse.org-common/classes/membership/membership.class.php
@@ -44,8 +44,7 @@
   private $member_name = "";
 
   function __construct(){
-    global $App;
-    $this->App = $App;
+    $this->App = new App();
     $this->members = array(
       'strategic' => array(
         'content_class' => 'tab-pane active',
@@ -63,13 +62,13 @@
         'img' => '/membership/images/type/enterprise-members.png',
         'title' => 'Enterprise Members',
       ),
-      'solutions' => array(
+      'contributing' => array(
         'content_class' => 'tab-pane',
-        'level' => 'solutions',
+        'level' => 'contributing',
         'list_class' => '',
         'members' => array(),
-        'img' => '/membership/images/type/solutions-members.png',
-        'title' => 'Solutions Members',
+        'img' => '/membership/images/type/contributing-members.png',
+        'title' => 'Contributing Members',
       ),
       'associate' => array(
         'content_class' => 'tab-pane',
@@ -79,6 +78,14 @@
         'img' => '/membership/images/type/associate-members.png',
         'title' => 'Associate Members',
       ),
+      'committer' => array(
+        'content_class' => 'tab-pane',
+        'level' => 'committer',
+        'list_class' => '',
+        'members' => array(),
+        'img' => '/membership/images/type/committer-members.png',
+        'title' => 'Committer Members',
+      )
     );
   }
 
@@ -123,7 +130,8 @@
       ORGI.large_mime as large_mime
     FROM organizations as ORG
     LEFT JOIN OrganizationInformation as ORGI on ORGI.OrganizationID = ORG.organization_id
-    WHERE ORG.member_type in ('SD', 'SC', 'AP', 'AS', 'ENTRP')";
+    WHERE ORG.member_type in ('SD', 'SC', 'AP', 'AS', 'ENTRP', 'OHAP')
+    and ORG.organization_id NOT IN (1322, 1324, 1325, 1328)";
 
     if (!is_null($this->id)) {
       $sql .= " and ORG.organization_id = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->id));
@@ -132,7 +140,7 @@
 
     $rs = $this->App->eclipse_sql($sql);
     while ($row = mysql_fetch_assoc($rs)) {
-      $row = $this->_mb_convert_encoding($row);
+      $row['name'] = $this->App->checkPlain($row['name']);
       $row['body'] = stripcslashes($row['body']);
       $row['full_text'] = stripcslashes($row['full_text']);
       $row['title_link'] = "";
@@ -152,12 +160,30 @@
       }
 
       $row['title_link'] .= $row['name'];
-      $small_logo_src = '/membership/images/eclipse-mp-member-144x69.png';
+      
+      $small_logo_src = '';
+      $large_logo_src = '';
+      switch($row['member_type']) {
+        case 'AP':
+        case 'OHAP':
+          $small_logo_src = '/membership/images/type/contributing-members.png';
+          $large_logo_src = '/membership/images/type/contributing-members.png';
+          break;
+        case 'AS':
+          $small_logo_src = '/membership/images/type/associate-members.png';
+          $large_logo_src = '/membership/images/type/associate-members.png';
+          break;
+        case 'SD':
+        case 'SC':
+          $small_logo_src = '/membership/images/type/strategic-members.png';
+          $large_logo_src = '/membership/images/type/strategic-members.png';
+          break;
+      }
       if (!empty($row['small_logo'])) {
         $small_logo_src = 'data:' . $row['small_mime'] . ';base64,' . base64_encode($row['small_logo']);
       }
-
-      $large_logo_src = '/membership/images/eclipse-mp-member-144x69.png';
+      $row['small_logo_src'] = $small_logo_src;
+      
       if (!empty($row['large_logo'])) {
         $large_logo_src = 'data:' . $row['large_mime'] . ';base64,' . base64_encode($row['large_logo']);
         $row['large_logo_website_link'] .= '<img src="' . $large_logo_src . '"  title="' . $row['name'] . '" class="img-responsive padding-bottom-25"/>';
@@ -165,6 +191,7 @@
       else{
         $row['large_logo_website_link'] = '<h1>' . $row['name']. '</h1>';
       }
+      $row['large_logo_src'] = $large_logo_src;
 
       $row['small_logo_link'] .= '<img src="' . $small_logo_src . '"  title="' . $row['name'] . '" class="img-responsive"/>';
       $row['large_logo_link'] .= '<img src="' . $large_logo_src . '"  title="' . $row['name'] . '" class="img-responsive"/>';
@@ -179,10 +206,10 @@
         $row['large_logo_website_link']  .= '</a>';
       }
 
-
       switch($row['member_type']) {
         case 'AP':
-          $this->members['solutions']['members'][] = $row;
+        case 'OHAP':
+          $this->members['contributing']['members'][] = $row;
           break;
         case 'AS':
           $this->members['associate']['members'][] = $row;
@@ -190,7 +217,8 @@
         case 'ENTRP':
           $this->members['enterprise']['members'][] = $row;
           break;
-        case 'SD' || 'SC':
+        case 'SD':
+        case 'SC':
           $this->members['strategic']['members'][] = $row;
           break;
       }
@@ -243,7 +271,6 @@
 
     $return = array();
     while ($row = mysql_fetch_assoc($result)) {
-      $row = $this->_mb_convert_encoding($row);
       $row['teaser'] = $this->_ellipsis($row['teaser']);
       $return[] = $row;
     }
@@ -283,7 +310,6 @@
     $result = $this->App->marketplace_sql($sql);
 
     while ($row = mysql_fetch_assoc($result)) {
-      $row = $this->_mb_convert_encoding($row);
       $row['teaser'] = empty($row['teaser']) ? '' : $this->_ellipsis($row['teaser']);
       $row['training'] = empty($row['training']) ? '' : $this->_ellipsis($row['training']);
       $row['consulting'] = empty($row['consulting']) ? '' : $this->_ellipsis($row['consulting']);
@@ -295,6 +321,35 @@
   }
 
   /**
+   * Fetch membership logo
+   *
+   * @return array
+   */
+  public function fetchMemberLogo() {
+    $unaccepted_ids = array(1322, 1324, 1325, 1328);
+    if (empty($this->id) || in_array((int)$this->id, $unaccepted_ids)) {
+      return array();
+    }
+
+    $sql = "SELECT
+      ORG.organization_id as id,
+      ORGI.small_logo as small_logo,
+      ORGI.large_logo as large_logo,
+      ORGI.small_mime as small_mime,
+      ORGI.large_mime as large_mime
+    FROM organizations as ORG
+    LEFT JOIN OrganizationInformation as ORGI on ORGI.OrganizationID = ORG.organization_id
+    WHERE ORG.member_type in ('SD', 'SC', 'AP', 'AS', 'ENTRP', 'OHAP')
+    and ORG.organization_id = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->id));
+    $rs = $this->App->eclipse_sql($sql);
+
+    while ($row = mysql_fetch_assoc($rs)) {
+      $this->profile['logo_information'] = $row;
+    }
+    return $this->profile;
+  }
+
+  /**
    * Fetch Member products
    *
    * @return multitype:|multitype:unknown
@@ -314,7 +369,6 @@
     $result = $this->App->eclipse_sql($sql);
 
     while ($row = mysql_fetch_assoc($result)) {
-      $row = $this->_mb_convert_encoding($row);
       $return[] = $row;
     }
 
@@ -402,21 +456,6 @@
   }
 
   /**
-   * Fix db encoding problems
-   *
-   * @param unknown $row
-   * @return unknown
-   */
-  private function _mb_convert_encoding($row){
-    foreach($row as $key => &$r) {
-      if ($key != 'large_logo' && $key != 'small_logo') {
-        $r = mb_convert_encoding($r, 'Windows-1252', 'UTF-8');
-      }
-    }
-    return $row;
-  }
-
-  /**
    * Add elipsis to a string
    *
    * @param string $string
diff --git a/eclipse.org-common/classes/mirrors/mirror.class.php b/eclipse.org-common/classes/mirrors/mirror.class.php
index c92759b..23b6045 100644
--- a/eclipse.org-common/classes/mirrors/mirror.class.php
+++ b/eclipse.org-common/classes/mirrors/mirror.class.php
@@ -30,7 +30,7 @@
   var $internal_host_pattern = "";

   var $last_verified = "";

 

-  public $exclude_string = "*.nfs* apitools/ apidocs/ archive/ archives/ /athena builds/N* */doc/* */documentation/* drops*/I* drops*/N* drops/M* *.jpg *.gif callisto/* compilelogs/ eclipse.org-common/ eclipse/testUpdates* eclipse/updates/3.2milestones /eclipse/updates/3.6-I-builds/ dev/TPTP* /tools/cdt/builds modeling/gmf/downloads/drops/B* *drops*/*/N* *drops*/*/I* *javadoc/ *javadocs/ linuxtools/N* *nightly* *Nightly* *staging* /webtools/downloads/drops/*/M* performance/ /releases/staging /releases/europa testresults/ /rt/eclipselink/nightly* /technology/cosmos /technology/ohf /technology/tigerstripe testcompilelogs/ testResults/ /tools/downloads /tools/orbit/committers */N201* */I201* */I.I201* */I-* */N-* *integration*/ xref/ */M20* /rt/eclipselink/maven.repo* */scripts* */logs* *drops4/X* *drops4/Y* */eclipse/updates/*-X* */eclipse/updates/*-Y* *.php*.* staging/* releases/staging/*";

+  public $exclude_string = "*.nfs* apitools/ apidocs/ archive/ archives/ /athena builds/N* */doc/* */documentation/* drops*/I* drops*/N* drops/M* *.jpg *.gif callisto/* compilelogs/ eclipse.org-common/ eclipse/testUpdates* eclipse/updates/3.2milestones /eclipse/updates/3.6-I-builds/ dev/TPTP* /tools/cdt/builds modeling/gmf/downloads/drops/B* *drops*/*/N* *drops*/*/I* *javadoc/ *javadocs/ linuxtools/N* *nightly* *Nightly* *staging* /webtools/downloads/drops/*/M* performance/ /releases/staging /releases/europa testresults/ /rt/eclipselink/nightly* /technology/cosmos /technology/ohf /technology/tigerstripe testcompilelogs/ testResults/ /tools/downloads /tools/orbit/committers */N201* */I201* */I.I201* */I-* */N-* *integration*/ xref/ */M20* /rt/eclipselink/maven.repo* */scripts* */logs* *drops4/X* *drops4/Y* *eclipse/updates/*-X* *eclipse/updates/*-Y* *.php*.* staging/* releases/staging/*";

 

 

   function getMirrorID() {

@@ -462,4 +462,4 @@
   }

 

 }

-?>
\ No newline at end of file
+?>

diff --git a/eclipse.org-common/classes/parser/feedparser.class.php b/eclipse.org-common/classes/parser/feedparser.class.php
index 52e293c..861862b 100644
--- a/eclipse.org-common/classes/parser/feedparser.class.php
+++ b/eclipse.org-common/classes/parser/feedparser.class.php
@@ -29,6 +29,20 @@
   private $count = 4;
 
   /**
+   * Feed object
+   *
+   * @var object
+   */
+  private $feeds = array();
+
+  /**
+   * Flag to match height on items
+   *
+   * @var bool
+   */
+  private $match_height = FALSE;
+
+  /**
    * Flag to only display press_releases
    *
    * @var string
@@ -97,6 +111,7 @@
   public function addPath($path = "") {
     if (is_string($path)) {
       $this->path[] = $path;
+      $this->_setFeeds($path);
       return TRUE;
     }
     return FALSE;
@@ -195,6 +210,18 @@
   }
 
   /**
+   * Get page number
+   *
+   * @return string
+   */
+  public function getPage() {
+    if (!empty($_GET['page']) && is_numeric($_GET['page'])) {
+      return $_GET['page'];
+    }
+    return 1;
+  }
+
+  /**
    * Set description limit
    *
    * @param number $limit
@@ -236,6 +263,26 @@
   }
 
   /**
+   * Set Match Height
+   *
+   * @param bool $match_height
+   */
+  public function setMatchHeight($match_height) {
+    if (is_bool($match_height)) {
+      $this->match_height = $match_height;
+    }
+  }
+
+  /**
+   * Get Match Height
+   *
+   * @return bool
+   */
+  public function getMatchHeight() {
+    return $this->match_height;
+  }
+
+  /**
    * Get ViewMore link
    *
    * @return string
@@ -279,42 +326,132 @@
 
     $output = '';
     if (!empty($this->items)) {
-      $output = '<ul class="news-list-media list-unstyled">';
+      $output .= '<div class="block-summary">';
       foreach ($this->items as $item) {
-        $output .= '<li><a href="' . $item['link'] . '" class="media media-link">';
-        $output .= '<p class="media-date">' . $item['date'] . '</p><h4 class="media-heading">' . $item['title'] . '</h4>';
+        $output .= '<div class="block-summary-item '. ($this->getMatchHeight() ? 'match-height-item' : "") .'">';
+        $output .= '<p>' . $item['date'] . '</p>';
+        $output .= '<h4><a href="'. $item['link'] .'">' . $item['title'] . '</a></h4>';
         if ($this->getLimit() > 0) {
-          $output .= '<p class="media-text">' . $item['description'] . '</p>';
+          $output .= '<p>' . $item['description'] . '</p>';
         }
-        $output .= ' </a></li>';
+        $output .= '</div>';
       }
-      $output .= '</ul>';
+      $output .= '</div>';
     }
 
     return $output;
   }
 
   /**
+   * Get the Next page link
+   *
+   * @return string
+   */
+  public function getPagination() {
+
+    $feeds = $this->_getFeeds();
+    if (empty($feeds)) {
+      return "";
+    }
+
+    // Count all the items of all feeds
+    $feed_items = 0;
+    foreach ($feeds as $feed) {
+      $feed_items += count($feed->channel->item);
+    }
+
+    // If the feed contains less items than the maximum allowed,
+    // we don't need pagination
+    if ($feed_items < $this->getCount()) {
+      return "";
+    }
+
+    $current_page = $this->getPage();
+    if (empty($current_page)) {
+      $current_page = 1;
+    }
+
+    $url_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . '?';
+
+    $url_queries = array(
+      'page' => 1
+    );
+
+    $links = array();
+
+    // Add the previous page link if needed
+    $previous_page = $current_page - 1;
+    if ($previous_page > 1) {
+      $url_queries['page'] = $previous_page;
+      $links[] = '<li><a aria-label="Previous" href="' . $url_path . http_build_query($url_queries) . '"><span aria-hidden="true">&laquo;</span></a></li>';
+    }
+
+    // Get the number of pages
+    $number_of_pages = ceil($feed_items / $this->count);
+
+    // Put the current page at the center of the pagination items
+    $start_pagination = $current_page - 5;
+
+    // Or make it the first item if its within the first 5 items
+    if ($start_pagination <= 0) {
+      $start_pagination = 1;
+    }
+
+    // Add the numerical links
+    for ($i = $start_pagination; $i <= $start_pagination + 9; $i++) {
+      $active = "";
+      if ($current_page == $i) {
+        $active = ' class="active"';
+      }
+      $url_queries['page'] = $i;
+      $links[] = '<li'. $active .'><a aria-label="Previous" href="' . $url_path . http_build_query($url_queries) . '">' . $i . '</a></li>';
+
+      if ($i >= $number_of_pages) {
+        break;
+      }
+    }
+
+    // Add the next page link if needed
+    $next_page = $current_page + 1;
+    if (!empty($feed_items) && $next_page <= $number_of_pages) {
+      $url_queries['page'] = $next_page;
+      $links[] = '<li><a aria-label="Next" href="' . $url_path . http_build_query($url_queries). '"><span aria-hidden="true">&raquo;</span></a></li>';
+    }
+
+    return '<nav aria-label="Page navigation"><ul class="pagination">' . implode($links) . '</ul></nav>';
+  }
+
+  /**
    * Parse the Feed
    *
    * @return boolean
    */
   private function _parseFeeds() {
-    $path = $this->getPath();
-    if (empty($path)) {
+    $feeds = $this->_getFeeds();
+    if (empty($feeds)) {
       return FALSE;
     }
 
     $count = 0;
-    foreach ($path as $p) {
-      if (file_exists($p)) {
-        $feed = simplexml_load_file($p);
+    foreach ($feeds as $feed) {
+
+      $start_range = 0;
+      $page = $this->getPage();
+      if (!empty($page) && $page > 1) {
+        $start_range = ($page - 1) * $this->count;
       }
 
       if (isset($feed) && $feed != FALSE) {
         foreach ($feed->channel->item as $item) {
-          $feed_array = array();
-          if ($count >= $this->count) {
+
+          // Skip the items that are part of the previous page
+          if ($count < $start_range) {
+            $count++;
+            continue;
+          }
+
+          // Break if we have enough feed items in the array
+          if (count($this->items) >= $this->count) {
             break;
           }
 
@@ -339,7 +476,6 @@
           );
 
           $this->items[] = $item_array;
-          $count++;
         }
       }
     }
@@ -350,4 +486,30 @@
     return FALSE;
   }
 
+  /**
+   * Set the feeds based on the path
+   */
+  private function _setFeeds($path = "") {
+
+    if (empty($path)) {
+      return FALSE;
+    }
+
+    $feed = simplexml_load_file($path);
+    if (empty($feed)) {
+      return FALSE;
+    }
+
+    $this->feeds[] = $feed;
+  }
+
+  /**
+   * Get the feeds
+   *
+   * @return array
+   */
+  private function _getFeeds() {
+    return $this->feeds;
+  }
+
 }
diff --git a/eclipse.org-common/classes/projects/forge.class.php b/eclipse.org-common/classes/projects/forge.class.php
index 8cd5924..989375b 100644
--- a/eclipse.org-common/classes/projects/forge.class.php
+++ b/eclipse.org-common/classes/projects/forge.class.php
@@ -64,22 +64,6 @@
           'hudson.eclipse.org',
           'ci.eclipse.org'
         )
-      ),
-      'locationtech' => array(
-        'id' => 'locationtech',
-        'name' => 'LocationTech',
-        'url' => 'https://www.locationtech.org',
-        'hudson_domain' => array(
-          'hudson.locationtech.org'
-        )
-      ),
-      'polarsys' => array(
-        'id' => 'polarsys',
-        'name' => 'PolarSys',
-        'url' => 'https://www.polarsys.org',
-        'hudson_domain' => array(
-          'hudson.polarsys.org'
-        )
       )
     );
 
diff --git a/eclipse.org-common/classes/releases/simultaneous_release.class.php b/eclipse.org-common/classes/releases/simultaneous_release.class.php
new file mode 100644
index 0000000..dce8032
--- /dev/null
+++ b/eclipse.org-common/classes/releases/simultaneous_release.class.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Copyright (c) 2019 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation)  - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+class SimultaneousRelease {
+
+  public $file_path = "";
+
+  /**
+   * Get the New and Noteworthy links from the list of projects
+   *
+   * @return array
+   */
+  function getNewAndNoteworthyLinks() {
+    $projects = $this->getProjects();
+    if (empty($projects)) {
+      return array();
+    }
+
+    if (!function_exists("sortByProjectName")) {
+      function sortByProjectName($a, $b) {
+        $a = $a['project_name'];
+        $b = $b['project_name'];
+        if ($a == $b) return 0;
+        return ($a < $b) ? -1 : 1;
+      }
+    }
+    uasort($projects, 'sortByProjectName');
+
+    $links = array();
+    foreach ($projects as $project) {
+      if (empty($project['project_name']) || empty($project['new_and_noteworthy_url']) || !filter_var($project['new_and_noteworthy_url'], FILTER_VALIDATE_URL)) {
+        continue;
+      }
+      $links[] = '<a href="'. $project['new_and_noteworthy_url'] .'">'. $project['project_name'] .'</a>';
+    }
+    return $links;
+  }
+
+  /**
+   * Get a list of the projects that contributed to the Simultaneous Release
+   *
+   * @return array
+   */
+  public function getProjects() {
+    $path = $this->getFilePath();
+    if (empty($path)) {
+      return array();
+    }
+    $json_data = json_decode(file_get_contents($path), TRUE);
+    if (!empty($json_data)) {
+      $json_data = reset($json_data);
+      if (!empty($json_data['projects'])) {
+        return $json_data['projects'];
+      }
+    }
+    return array();
+  }
+
+  /**
+   * Set the file path
+   *
+   * @param string $path
+   *
+   * @return bool
+   */
+  public function setFilePath($path) {
+
+    if (empty($path) || !file_exists($path)) {
+      return FALSE;
+    }
+
+    $this->file_path = $path;
+    return TRUE;
+  }
+
+  /**
+   * Get the file path
+   *
+   * @return string
+   */
+  public function getFilePath() {
+    return $this->file_path;
+  }
+
+}
diff --git a/eclipse.org-common/classes/rest/committerpaperwork.class.php b/eclipse.org-common/classes/rest/committerpaperwork.class.php
index e754a28..d626ac0 100644
--- a/eclipse.org-common/classes/rest/committerpaperwork.class.php
+++ b/eclipse.org-common/classes/rest/committerpaperwork.class.php
@@ -42,7 +42,7 @@
    * @param array $data
    */
   public function createCommitterPaperwork($username = NULL, $data = array()) {
-    return $this->post('committer/paperwork/' . $username, json_encode($data));
+    return $this->post('foundation/paperwork/' . $username, json_encode($data));
   }
 
   /**
@@ -52,7 +52,7 @@
    * @param unknown $id
    */
   public function deleteCommitterPaperwork($username = "", $id = "", $etag = "") {
-    $response = $this->delete('committer/paperwork/' . $username . '/' . $id);
+    $response = $this->delete('foundation/paperwork/' . $username . '/' . $id);
     $this->unsetHeader('If-Match');
     return $response;
   }
@@ -71,7 +71,7 @@
       ));
     }
 
-    $response = $this->get('committer/paperwork/' . $username . '/' . $id);
+    $response = $this->get('foundation/paperwork/' . $username . '/' . $id);
     if (isset($response->code) && $response->code == 200) {
       $data = json_decode($response->body);
       $this->data[$data->id] = $data;
@@ -94,7 +94,7 @@
       'If-Match' => '"' . $etag . '"',
     ));
 
-    $response = $this->put('committer/paperwork/' . $username . '/' . $id, json_encode($data));
+    $response = $this->put('foundation/paperwork/' . $username . '/' . $id, json_encode($data));
     $this->unsetHeader('If-Match');
     return $response;
   }
@@ -109,7 +109,7 @@
    */
   public function indexCommitterPaperwork($username = NULL, $params = array()) {
 
-    $url = 'committer/paperwork';
+    $url = 'foundation/paperwork';
     if (!is_null($username) && is_string($username)) {
       $url .= '/' . $username;
     }
@@ -148,7 +148,7 @@
    * @param int $id
    */
   public function targetedActionStartProvisioning($username = NULL, $id = "", $body = array()) {
-    return $this->post('committer/paperwork/' . $username . '/provisioning/' . $id, json_encode($body));
+    return $this->post('foundation/paperwork/' . $username . '/provisioning/' . $id, json_encode($body));
   }
 
   /**
@@ -158,7 +158,7 @@
    * @param int $id
    */
   public function targetedActionRetireCommitter($username = NULL, $body = array()) {
-    return $this->post('committer/paperwork/' . $username . '/retire', json_encode($body));
+    return $this->post('foundation/paperwork/' . $username . '/retire', json_encode($body));
   }
 
   /**
@@ -263,7 +263,8 @@
       'election_nid',
       'election_status',
       'committer_paperwork_nid',
-      'committer_paperwork_status'
+      'committer_paperwork_status',
+      'spec_project_working_group'
     );
 
     $string_fields = array(
diff --git a/eclipse.org-common/classes/rest/githubApi.class.php b/eclipse.org-common/classes/rest/githubApi.class.php
new file mode 100644
index 0000000..627f355
--- /dev/null
+++ b/eclipse.org-common/classes/rest/githubApi.class.php
@@ -0,0 +1,318 @@
+<?php
+/**
+ * Copyright (c) 2019 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+require_once ('lib/eclipseussblob.class.php');
+
+/**
+ * GithubApi class
+ *
+ * Usage example:
+ *
+ * include_once('githubApi.class.php');
+ * $GithubApi = new GithubApi();
+ * $GithubApi->loginSSO();
+ *
+ * @author ericpoirier
+ */
+class GithubApi extends EclipseUSSBlob {
+
+  /**
+   * Constuctor
+   */
+  function __construct(App $App = NULL) {
+    parent::__construct($App);
+    $this->setBaseUrl("https://api.github.com");
+  }
+
+  /**
+   * Get a organization's teams
+   *
+   * @param string $org
+   * @param string $team_id
+   *
+   * @return object
+   */
+  function getOrganizationTeams($org = "", $team_id = "") {
+
+    if (empty($org) || !is_string($org)) {
+      return NULL;
+    }
+
+    $url = 'orgs/' . $org . '/teams';
+    if (!empty($team_id) && is_numeric($team_id)) {
+      $url .= "/" . $team_id;
+    }
+
+    $response = $this->get($url);
+
+    return $response;
+  }
+
+  /**
+   * Get a list of members for a specific organization
+   *
+   * @param string $org
+   *
+   * @return object
+   */
+  function getOrganizationMembers($org = "") {
+    if (empty($org) || !is_string($org)) {
+      return NULL;
+    }
+
+    $response = $this->get("orgs/" . $org . "/members");
+
+    return $response;
+  }
+
+  /**
+   * Validate if a user is a member of an organization
+   *
+   * @param string $org
+   * @param string $username
+   *
+   * return object
+   */
+  function validateOrganizationMembership($org = "", $username = "") {
+    if (empty($org) || !is_string($org)) {
+      return NULL;
+    }
+
+    if (empty($username) || !is_string($username)) {
+      return NULL;
+    }
+
+    $response = $this->get("orgs/" . $org . "/members/" . $username);
+
+    return $response;
+  }
+
+  /**
+   * Get the contributors team from an organization
+   *
+   * @param string @org
+   *
+   * @return array
+   */
+  function getOrganizationContributorsTeam($org = "") {
+    $teams_request = $this->getOrganizationTeams($org);
+
+    if (empty($teams_request) || empty($teams_request->body) || $teams_request->code !== 200) {
+      return FALSE;
+    }
+
+    $teams = drupal_json_decode($teams_request->body);
+
+    $team = array();
+    foreach ($teams as $team_array) {
+      if (!empty($team_array['slug']) && strpos($team_array['slug'], 'contributors') !== FALSE) {
+        $team = $team_array;
+        break;
+      }
+    }
+
+    if (empty($team["id"])) {
+      return FALSE;
+    }
+
+    return $team;
+  }
+
+  /**
+   * Get a team based on the team ID
+   *
+   * @param string $team_id
+   *
+   * @return object
+   */
+  function getTeam($team_id = "") {
+
+    if (empty($team_id) || !is_numeric($team_id)) {
+      return NULL;
+    }
+
+    return $this->get('teams/' . $team_id);
+  }
+
+  /**
+   * Get a user based on the provided username
+   *
+   * @param string $username
+   *
+   * @return object
+   */
+  function getUser($username = "") {
+
+    if (empty($username) || !is_string($username)) {
+      return NULL;
+    }
+
+    return $this->get('users/' . $username);
+  }
+
+  /**
+   * Get a team's members
+   *
+   * @param string $team_id
+   *
+   * return object
+   */
+  function getTeamMembers($team_id = "", $username = "") {
+
+    if (empty($team_id) || !is_numeric($team_id)) {
+      return NULL;
+    }
+
+    $url = 'teams/' . $team_id . '/members';
+    if (!empty($username) && is_string($username)) {
+      $url .= '/' . $username;
+    }
+
+    return $this->get($url);
+  }
+
+  /**
+   * Get a list of pending invitations to become a member to a team
+   *
+   * @param string $team_id
+   *
+   * @return object
+   */
+  function getPendingTeamMembers($team_id = "") {
+
+    if (empty($team_id) || !is_numeric($team_id)) {
+      return NULL;
+    }
+
+    return $this->get('teams/' . $team_id . '/invitations');
+  }
+
+  /**
+   * Get a Github user
+   *
+   * @param string $username
+   *
+   * @return object
+   */
+  function getUsers($username = "") {
+
+    if (empty($username) || !is_string($username)) {
+      return NULL;
+    }
+
+    return $this->get('users/' . $username);
+  }
+
+  /**
+   * Create a team member in a specific team
+   *
+   * @param string $team_id
+   * @param string $username
+   *
+   * @return object
+   */
+  function createTeamMember($team_id = "", $username = "") {
+
+    if (empty($team_id) || !is_numeric($team_id) || empty($username) || !is_string($username)) {
+      return NULL;
+    }
+
+    return $this->put('teams/' . $team_id . '/memberships/' . $username);
+  }
+
+  /**
+   * Remove a team member from a specific team
+   *
+   * @param string $team_id
+   * @param string $username
+   *
+   * @return object
+   */
+  function removeTeamMember($team_id = "", $username = "") {
+
+    if (empty($team_id) || !is_numeric($team_id) || empty($username) || !is_string($username)) {
+      return NULL;
+    }
+
+    return $this->delete('teams/' . $team_id . '/members/' . $username);
+  }
+
+  /**
+   * Create a team in a specific organization
+   *
+   * @param string $org
+   * @param array $data
+   *
+   * @return object
+   */
+  function createTeam($org = "", $data = "") {
+
+    if (empty($org) || empty($data) || !is_string($org) || !is_array($data)) {
+      return NULL;
+    }
+
+    return $this->post("orgs/" . $org . "/teams", json_encode($data));
+  }
+
+  /**
+   * Remove a team
+   *
+   * @param string $team_id
+   *
+   * @return object
+   */
+  function removeTeam($team_id = "") {
+
+    if (empty($team_id) || !is_numeric($team_id)) {
+      return NULL;
+    }
+
+    return $this->delete("teams/" . $team_id);
+  }
+
+  /**
+   * Add or update a repo in a team
+   *
+   * @param string $team_id
+   * @param string $owner
+   * @param string $repo
+   *
+   * @return object
+   */
+  function updateTeamRepo($team_id = "", $owner = "", $repo = "") {
+
+    if (empty($team_id) || !is_numeric($team_id) || empty($owner) || !is_string($owner) || empty($repo) || !is_string($repo)) {
+      return NULL;
+    }
+
+    return $this->put("teams/" . $team_id . "/repos/" . $owner . "/" . $repo);
+  }
+
+  /**
+   * Remove a repo from a team
+   *
+   * @param string $team_id
+   * @param string $owner
+   * @param string $repo
+   *
+   * @return object
+   */
+  function removeTeamRepo($team_id = "", $owner = "", $repo = "") {
+
+    if (empty($team_id) || !is_numeric($team_id) || empty($owner) || !is_string($owner) || empty($repo) || !is_string($repo)) {
+      return NULL;
+    }
+
+    return $this->delete("teams/" . $team_id . "/repos/" . $owner . "/" . $repo);
+  }
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/rest/githubRepository.class.php b/eclipse.org-common/classes/rest/githubRepository.class.php
new file mode 100644
index 0000000..a1dc92f
--- /dev/null
+++ b/eclipse.org-common/classes/rest/githubRepository.class.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Copyright (c) 2019 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+/**
+ * GithubRepository class
+ *
+ * Usage example:
+ *
+ * include_once('GithubRepository.class.php');
+ * $GithubApi = new GithubRepository();
+ *
+ * @author ericpoirier
+ */
+class GithubRepository {
+
+  /**
+   * Repository url
+   *
+   * var string
+   */
+  public $repo_url = "";
+
+  /**
+   * Get the repository's url
+   *
+   * @return string
+   */
+  public function getRepoUrl() {
+    return $this->repo_url;
+  }
+
+  /**
+   * Set the repository's url
+   *
+   * @param string $url
+   */
+  public function setRepoUrl($url = "") {
+    $url = filter_var($url, FILTER_SANITIZE_URL);
+    if (!empty($url)) {
+      $this->repo_url = $url;
+    }
+  }
+
+  /**
+   * Get the organization's name
+   *
+   * @return string
+   */
+  public function getOrganizationName() {
+    $repo = $this->repoUrlArray();
+    if (empty($repo[0])) {
+      return "";
+    }
+    return $repo[0];
+  }
+
+  /**
+   * Get the team's name
+   *
+   * @return string
+   */
+  public function getContributorTeamName() {
+    $repo = $this->repoUrlArray();
+    if (empty($repo[0]) || empty($repo[1])) {
+      return "";
+    }
+    return $repo[0] . '-' . $repo[1] . '-contributors';
+  }
+
+  /**
+   * Get the repository's name
+   *
+   * @return string
+   */
+  public function getRepoName() {
+    $repo = $this->repoUrlArray();
+    if (empty($repo[1])) {
+      return "";
+    }
+    return $repo[1];
+  }
+
+  /**
+   * Get the array result of the repository's url
+   *
+   * @return array
+   */
+  private function repoUrlArray() {
+    if (empty($this->repo_url)) {
+      return array();
+    }
+    return explode('/', preg_replace('/http(s|)?:\/\/[www\.]?github.com\//', '', $this->repo_url));
+  }
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/rest/lib/eclipseussblob.class.php b/eclipse.org-common/classes/rest/lib/eclipseussblob.class.php
index 43affa1..6d88d23 100644
--- a/eclipse.org-common/classes/rest/lib/eclipseussblob.class.php
+++ b/eclipse.org-common/classes/rest/lib/eclipseussblob.class.php
@@ -38,7 +38,7 @@
 
     switch ($this->getEnvShortName()) {
       case 'local':
-        $this->setBaseUrl('https://api.php53.dev.docker');
+        $this->setBaseUrl('https://api.php56.dev.docker');
         break;
       case 'staging':
         $this->setBaseUrl('https://api-staging.eclipse.org');
@@ -89,7 +89,7 @@
    *
    * @return Response $data
    */
-  public function getBlob($application_token = "", $blob_key = "", $username = "") {
+  public function getBlob($application_token = "", $blob_key = "") {
     $etag = $this->getEtag();
     if (!empty($etag)) {
       $this->setHeader(array(
@@ -98,9 +98,6 @@
     }
 
     $url = 'uss/blob/';
-    if (!empty($username)) {
-      $url =  'account/profile/' . $username . '/blob/';
-    }
     $url .= $application_token . '/' . $blob_key;
     $data = $this->get($url);
     $this->unsetHeader('If-None-Match');
@@ -116,11 +113,8 @@
    *
    * @return Response $data
    */
-  public function indexBlob($application_token = "", $page = 1, $pagesize = 20, $username = "") {
+  public function indexBlob($application_token = "", $page = 1, $pagesize = 20) {
     $url = 'uss/blob/' . $application_token;
-    if (!empty($username)) {
-      $url = 'account/profile/' . $username . '/blob/' . $application_token;
-    }
     $data = $this->get($url . '?page=' . $page . '&pagesize=' . $pagesize);
     return $data;
   }
@@ -134,8 +128,8 @@
    *
    * @return Response $data
    */
-  public function indexAllBlob($application_token = "", $page = 1, $pagesize = 20, $username = "") {
-    $data = $this->indexBlob($application_token, $page, $pagesize, $username);
+  public function indexAllBlob($application_token = "", $page = 1, $pagesize = 20) {
+    $data = $this->indexBlob($application_token, $page, $pagesize);
 
     $return = array();
     $return[] = $data;
diff --git a/eclipse.org-common/classes/rest/member.class.php b/eclipse.org-common/classes/rest/member.class.php
new file mode 100644
index 0000000..0795c11
--- /dev/null
+++ b/eclipse.org-common/classes/rest/member.class.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+
+require_once ('lib/eclipseussblob.class.php');
+
+/**
+ * Member class
+ *
+ * Usage example:
+ *
+ * include_once('member.class.php');
+ * $Member = new Member();
+ * $Member->loginSSO();
+ *
+ * @author chrisguindon
+ */
+class Member extends EclipseUSSBlob {
+
+  /**
+   * Class constructor
+   */
+  function __construct(App $App = NULL) {
+    parent::__construct($App);
+  }
+
+  /**
+   * Fetch all members
+   *
+   * @param array params
+   *
+   * return array
+   */
+  public function indexMember($params = array()) {
+    $url = 'foundation/member';
+    if (!empty($params)) {
+      $query = http_build_query($params);
+      $url .= "?" . $query;
+    }
+
+    $response = $this->get($url);
+    return $response;
+  }
+
+  /**
+   * Retrieve a member based on the organization id
+   *
+   * @param string $organization_id
+   *
+   * @return array
+   */
+  public function retrieveMember($organization_id = "") {
+    if (!is_numeric($organization_id)) {
+      return array();
+    }
+    $response = $this->get('foundation/member/' . $organization_id);
+    $this->unsetHeader('If-Match');
+    return $response;
+  }
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/rest/userDeleteRequest.class.php b/eclipse.org-common/classes/rest/userDeleteRequest.class.php
new file mode 100644
index 0000000..5ad02e7
--- /dev/null
+++ b/eclipse.org-common/classes/rest/userDeleteRequest.class.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *    Christopher Guindon (Eclipse Foundation) - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+
+require_once ('lib/eclipseussblob.class.php');
+
+/**
+ * UserDeleteRequest class
+ *
+ * Usage example:
+ *
+ * include_once('userDeleteRequest.class.php');
+ * $UserDeleteRequest = new UserDeleteRequest();
+ *
+ * @author chrisguindon
+ */
+class UserDeleteRequest extends EclipseUSSBlob {
+
+  /**
+   * Delete a UserDeleteRequest
+   *
+   * @param int $id
+   *
+   * @return Response
+   */
+  public function deleteUserDeleteRequest($id = "") {
+    if (!empty($id) && is_numeric($id)) {
+      return $this->delete('account/user_delete_request/' .  $id);
+    }
+    return array();
+  }
+
+  /**
+   * Query UserDeleteRequest entities
+   *
+   * @param array $query
+   *
+   * @return Response
+   */
+  public function indexUserDeleteRequest($query = array()) {
+    $query_string = "";
+    if (!empty($query) || !is_array($query)) {
+      $query_string = '?' . http_build_query($query);
+    }
+
+    $response = $this->get("account/user_delete_request/" . $query_string);
+    return $response;
+  }
+
+  /**
+   * Update an UserDeleteRequest entity
+   *
+   * @param int $id
+   * @param string $status
+   *
+   * @return Response
+   */
+   public function updateDeleteRequest($id = "", $status = "") {
+     if (!empty($id) && is_numeric($id) && is_numeric($status)) {
+       return $this->put('account/user_delete_request/' . $id, json_encode(array('status' => $status)));
+     }
+     return array();
+  }
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/rest/userinformation.class.php b/eclipse.org-common/classes/rest/userinformation.class.php
index 2ecf0f9..e4ee68b 100644
--- a/eclipse.org-common/classes/rest/userinformation.class.php
+++ b/eclipse.org-common/classes/rest/userinformation.class.php
@@ -92,4 +92,19 @@
     $this->unsetHeader('If-Match');
     return $response;
   }
+
+  /**
+   * Trigger an user deletion process
+   *
+   * @param string $identifier
+   *
+   * @return array|Response
+   */
+  public function targetedActionDeleteUser($identifier){
+    if (empty($identifier)) {
+      return array();
+    }
+    $response = $this->post('account/profile/' . $identifier. '/user_delete_request');
+    return $response;
+  }
 }
\ No newline at end of file
diff --git a/eclipse.org-common/classes/themes/baseTheme.class.php b/eclipse.org-common/classes/themes/baseTheme.class.php
index a9811f3..f55b219 100644
--- a/eclipse.org-common/classes/themes/baseTheme.class.php
+++ b/eclipse.org-common/classes/themes/baseTheme.class.php
@@ -50,6 +50,13 @@
   protected $Breadcrumb = NULL;
 
   /**
+   * Display footer prefix
+   *
+   * @var bool
+   */
+  protected $display_footer_prefix = TRUE;
+
+  /**
    * Display header right html
    *
    * @var bool
@@ -98,6 +105,18 @@
   protected $extra_header_html = "";
 
   /**
+   * Featured story xml path
+   */
+  protected $featured_story_xml = "";
+
+  /**
+   * Links for the footer
+   *
+   * @var array
+   */
+  protected $footer_links = array();
+
+  /**
    * Page HTML content
    *
    * @var string
@@ -232,6 +251,13 @@
   protected $toolbar_left_content = "";
 
   /**
+   * Position of sidebar Nav
+   *
+   * @var string
+   */
+  protected $nav_position = "default";
+
+  /**
    * Constructor
    */
   function __construct($App = NULL) {
@@ -297,6 +323,7 @@
     // Set attributes on main content
     $this->setAttributes('main', 'main', 'role');
     $this->setAttributes('main', 'no-promo');
+    $this->setAttributes('main', 'content', 'id');
     $this->setAttributes('main-container', 'novaContent');
     $this->setAttributes('main-container', 'novaContent', 'id');
 
@@ -315,7 +342,7 @@
     $this->setAttributes('footer4', 'footer-other', 'id');
 
     // Default theme js file
-    $this->setAttributes('script-theme-main-js', $this->getThemeUrl('solstice') . 'public/javascript/main.min.js?var=1.0', 'src');
+    $this->setAttributes('script-theme-main-js', $this->getThemeUrl('solstice') . 'public/javascript/main.min.js?var=0.0.130', 'src');
   }
 
   /**
@@ -324,10 +351,18 @@
    * @return boolean
    */
   public function hasCookieConsent() {
-    if (isset($_COOKIE['eclipse_cookieconsent_status']) && $_COOKIE['eclipse_cookieconsent_status'] === 'allow') {
-      return TRUE;
-    }
-    return FALSE;
+    return $this->App->hasCookieConsent();
+  }
+
+  /**
+   * Get a featured story from the provided xml file
+   *
+   * @param $xml_file
+   *
+   * @return array
+   */
+  public function getFeaturedStoryFooter() {
+   return '<div class="eclipsefdn-featured-story featured-footer" data-publish-target="eclipse_org"><div class="container featured-container"></div></div>';
   }
 
   /**
@@ -484,6 +519,7 @@
       'width',
       'src',
       'title',
+      'style'
     );
 
     // If type is null, we shall return the string with both class and id.
@@ -545,29 +581,32 @@
       'width',
       'src',
       'title',
+      'style'
     );
 
     $type = strtolower($type);
-    $value = explode(' ', $value);
-    foreach ($value as $val) {
-      if (in_array($type, $allowed_type) && is_string($element) && !empty($element) && !empty($val)) {
-        switch ($type) {
-          case 'class':
-            // Append classes instead of overriting them.
-            // This way we can set multiple classes for differents contexts.
-            if (!isset($this->attributes[$type][$element]) || !in_array($val, $this->attributes[$type][$element])) {
-              $this->attributes['class'][$element][] = $val;
-            }
-            break;
+    if (!in_array($type, $allowed_type) || !is_string($element) || empty($element) || empty($value)) {
+      return $this->attributes;
+    }
 
-          // For everything else, we only keep the last value set.
-          default:
-            $this->attributes[$type][$element] = array(
-              $val
-            );
-            break;
+    switch ($type) {
+      case 'class':
+        $value = explode(' ', $value);
+        foreach ($value as $val) {
+          // Append classes instead of overriting them.
+          // This way we can set multiple classes for differents contexts.
+          if (!isset($this->attributes[$type][$element]) || !in_array($val, $this->attributes[$type][$element])) {
+            $this->attributes['class'][$element][] = $val;
+          }
         }
-      }
+        break;
+
+      // For everything else, we only keep the last value set.
+      default:
+        $this->attributes[$type][$element] = array(
+          $value
+        );
+        break;
     }
     return $this->attributes;
   }
@@ -762,6 +801,27 @@
   }
 
   /**
+   * Build a url based on a path and a set of options
+   *
+   * @param string $path
+   * @param array $options
+   *
+   * @return string
+   */
+  public function buildUrl($path = "", $options = array()) {
+
+    if (!empty($options['absolute']) && !filter_var($path, FILTER_VALIDATE_URL)) {
+      return $path;
+    }
+
+    if (!empty($options['query'])) {
+      $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . http_build_query($options['query']);
+    }
+
+    return $path;
+  }
+
+  /**
    * Get Call For Action Button Html
    *
    * @return string
@@ -910,6 +970,35 @@
   }
 
   /**
+   * Get $display_footer_prefix
+   *
+   * @return bool
+   */
+  public function getDisplayFooterPrefix() {
+    return $this->display_footer_prefix;
+  }
+
+  /**
+   * Set $display_footer_prefix
+   *
+   * @param bool $display
+   */
+  public function setDisplayFooterPrefix($display = TRUE) {
+    if ($display !== FALSE) {
+      $display = TRUE;
+    }
+
+    // Remove the footer offset class when we hide the footer prefix
+    if ($display === FALSE) {
+      $main_container_classes = str_replace(' footer-offset', '', $this->getThemeVariables('main_container_classes'));
+      $App = $this->_getApp();
+      $App->setThemeVariables(array('main_container_classes' => $main_container_classes));
+      $this->resetAttributes('main-container', 'class');
+    }
+    $this->display_footer_prefix = $display;
+  }
+
+  /**
    * Get $display_google_search
    */
   public function getDisplayGoogleSearch() {
@@ -1079,10 +1168,17 @@
         break;
     }
 
-    $return = '<link rel="stylesheet" href="' . $this->getThemeUrl('solstice') . 'public/stylesheets/' . $styles_name . '.min.css?v1.0"/>' . PHP_EOL;
+    $return = '<link rel="stylesheet" href="' . $this->getThemeUrl('solstice') . 'public/stylesheets/' . $styles_name . '.min.css?v0.130"/>' . PHP_EOL;
 
     // Add og:metatags if they haven't been set.
     // @todo: deprecated og functions in App().
+    if (!$this->getMetatagByKey('description')) {
+      $this->setMetatags('description', array(
+        'name' => 'description',
+        'content' => $this->getMetaDescription(),
+      ));
+    }
+
     if (!$this->getMetatagByKey('og:description')) {
       $this->setMetatags('og:description', array(
         'property' => 'og:description',
@@ -1205,7 +1301,7 @@
         $return .= '<link href="//fonts.googleapis.com/css?family=Open+Sans:400,700,300,600,100" rel="stylesheet" type="text/css"/>';
         break;
       default:
-        $return .= '<link href="//fonts.googleapis.com/css?family=Libre+Franklin:400,700,300,600,100" rel="stylesheet" type="text/css"/>';
+        $return .= '<link href="https://fonts.googleapis.com/css2?family=Libre+Franklin:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet" type="text/css"/>';
     }
 
     return $return. PHP_EOL;
@@ -1221,6 +1317,85 @@
   }
 
   /**
+   * Get links for the footer
+   *
+   * @param string $region
+   *
+   * @return string
+   */
+  public function getFooterLinks($region) {
+
+    $accepted_regions = array("region_1", "region_2", "region_3", "region_4", "region_5");
+
+    if (empty($region) || !in_array($region, $accepted_regions)) {
+      return "";
+    }
+
+    if (!function_exists("sortByWeight")) {
+      function sortByWeight($a, $b) {
+        $a = $a['weight'];
+        $b = $b['weight'];
+        if ($a == $b) return 0;
+        return ($a < $b) ? -1 : 1;
+      }
+    }
+    usort($this->footer_links, "sortByWeight");
+
+    $footer_links = '';
+    foreach ($this->footer_links as $footer_link) {
+      if ($footer_link['region'] !== $region) {
+        continue;
+      }
+      $footer_links .= '<li><a href="'. $footer_link['url'] .'">'. $footer_link['title'] .'</a></li>';
+    }
+
+    return '<ul class="nav">' . $footer_links . '</ul>';
+  }
+
+  /**
+   * Set Links for the footer
+   *
+   * @param string $title
+   * @param string $url
+   * @param string $region
+   * @param int $weight
+   */
+  public function setFooterLinks($element = "", $title = "", $url = "", $region = "", $weight = 0) {
+
+    $accepted_regions = array("region_1", "region_2", "region_3", "region_4", "region_5");
+
+    if (empty($element) || empty($title) || empty($url) || empty($region) || !in_array($region, $accepted_regions) || !is_numeric($weight)) {
+      return FALSE;
+    }
+
+    $this->footer_links[$element] = array(
+        'title' => $title,
+        'url' => $url,
+        'region' => $region,
+        'weight' => $weight
+    );
+  }
+
+  /**
+   * Remove Footer links
+   *
+   * @param string $element
+   */
+  public function removeFooterLinks($element) {
+
+    if (empty($element)) {
+      return FALSE;
+    }
+
+    foreach ($this->footer_links as $key => $footer_link) {
+      if ($key !== $element) {
+        continue;
+      }
+      unset($this->footer_links[$element]);
+    }
+  }
+
+  /**
    * Get Html of Footer prexix
    *
    * This is a way for sub-themes to inject
@@ -1552,10 +1727,40 @@
   }
 
   /**
+   * Set Nav Position
+   *
+   * @param string $position
+   * @return string
+   */
+  public function setNavPosition ($position = 'default') {
+    $valid_position = array('default', 'left');
+    $position = strtolower($position);
+    if (in_array($position, $valid_position)) {
+      $this->nav_position = $position;
+    }
+    return $this->nav_position;
+  }
+
+  /**
+   * Get Nav Position
+   *
+   * @return string
+   */
+  public function getNavPosition () {
+    return $this->nav_position;
+  }
+
+  /**
    * Get page $html
    */
   public function getHtml() {
-
+    $nav_position = $this->getNavPosition();
+    $content_col_classes = ($this->getThemeFile('nav') ? 'col-md-18' : 'col-md-24');
+    $nav_col_classes = 'col-md-6';
+    if ($nav_position === 'left') {
+      $content_col_classes .= ' col-md-push-6';
+      $nav_col_classes .= ' col-md-pull-18';
+    }
     // Define the body content
     $body = $this->getDeprecatedMessage();
     $body .= $this->getHeaderNav();
@@ -1563,36 +1768,12 @@
     $body .= $this->getThemeVariables('main_container_html');
     $body .= $this->html;
 
-    // If Title is in the Header
-    $html_page_title = "";
-    if ($this->getDisplayHeaderTitle()) {
-      // Remove attributes of breadcrumbs
-      $this->removeAttributes('breadcrumbs', 'breadcrumbs-default-margin');
-
-      // Set attributes for sidebar
-      $this->setAttributes('main-sidebar', 'hidden-sm hidden-xs');
-
-      // Define Main page Title
-      $html_page_title = '<div class="main-page-title"><div class="container">';
-      $html_page_title .= '<div class="' . ($nav = $this->getThemeFile('nav') ? 'col-sm-18' : 'col-sm-24') . ' reset">';
-      $html_page_title .= '<h1>' . $this->getPageTitle() . '</h1>';
-      $html_page_title .= '</div>';
-      if ($nav = $this->getThemeFile('nav')) {
-        $html_page_title .= '<div class="col-md-6">' . $nav . '</div>';
-      }
-      $html_page_title .= '</div></div>';
-
-      // Reset attributes for sidebar that will be in the body
-      $this->removeAttributes('main-sidebar', 'hidden-sm hidden-xs');
-      $this->setAttributes('main-sidebar', 'hidden-md hidden-lg');
-    }
-
     // set a different body if there's a sidebar
     if ($nav = $this->getThemeFile('nav')) {
       $body_content = $body;
       $body = '<div class="row">';
-      $body .= '<div class="col-md-18">' . $body_content . '</div>';
-      $body .= '<div class="col-md-6">' . $nav . '</div>';
+      $body .= '<div class="' . $content_col_classes . ' main-col-content">' . $body_content . '</div>';
+      $body .= '<div class="' . $nav_col_classes . ' main-col-sidebar-nav">' . $nav . '</div>';
       $body .= '</div>';
     }
 
@@ -1600,13 +1781,11 @@
     return <<<EOHTML
       {$this->getBreadcrumbHtml()}
       <main{$this->getAttributes('main')}>
-        {$html_page_title}
         <div{$this->getAttributes('main-container')}>
           {$body}
         </div>
       </main>
 EOHTML;
-
   }
 
   /**
@@ -1766,9 +1945,9 @@
     }
     $Menu = new Menu();
     $Menu->setMenuItemList(array());
-    $Menu->addMenuItem("Members", $base_url . "membership/", "_self");
-    $Menu->addMenuItem("Working Groups", $base_url . "org/workinggroups/", "_self");
     $Menu->addMenuItem("Projects", $base_url . "projects/", "_self");
+    $Menu->addMenuItem("Working Groups", $base_url . "org/workinggroups/", "_self");
+    $Menu->addMenuItem("Members", $base_url . "membership/", "_self");
     return $Menu;
   }
 
@@ -1872,12 +2051,22 @@
       'caption' => 'IRC'
     );
 
+    $variables['Participate'][] = array(
+      'url' => 'https://www.eclipse.org/org/research/',
+      'caption' => 'Research'
+    );
+
     $variables['Eclipse IDE'][] = array(
       'url' => $base_url . 'downloads',
       'caption' => 'Download'
     );
 
     $variables['Eclipse IDE'][] = array(
+      'url' => $base_url . 'eclipseide',
+      'caption' => 'Learn More'
+    );
+
+    $variables['Eclipse IDE'][] = array(
       'url' => 'https://help.eclipse.org',
       'caption' => 'Documentation'
     );
@@ -1906,11 +2095,20 @@
   }
 
   /**
+   * Get Menu Prefix
+   *
+   * @return string
+   */
+  public function getMainMenuPrefix() {
+    return "";
+  }
+
+  /**
    * Get Menu Suffix
    *
    * @return string
    */
-  protected function _getMenuSuffix(){
+  public function getMenuSuffix(){
     return "";
   }
 
@@ -2069,32 +2267,42 @@
    */
   public function getSessionVariables($id = "") {
     if (empty($this->session_variables)) {
-      $this->session_variables['session'] = array(
-        'Friend' => NULL,
-        'name' => '',
-        'last_name' => ''
+      // Define the default toolbar links
+      $toolbar_links = array(
+        'user_login' => '<li><a class="toolbar-link" href="' . $this->getBaseUrlLogin() . '/user/login/' . $this->_getTakeMeBack() . '"><i class="fa fa-sign-in"></i> Log in</a></li>',
+        'manage_cookies' => '<a class="toolbar-link toolbar-manage-cookies dropdown-toggle"><i class="fa fa-wrench"></i> Manage Cookies</a>',
+        'dropdown' => '',
+        'logout' => ''
       );
 
-      $this->session_variables['create_account_link'] = '<a href="' . $this->getBaseUrlLogin() . '/user/register"><i class="fa fa-user fa-fw"></i> Create account</a>';
-      $this->session_variables['my_account_link'] = '<a href="' . $this->getBaseUrlLogin() . '/user/login/' . $this->_getTakeMeBack() . '"><i class="fa fa-sign-in fa-fw"></i> Log in</a>';
-      $this->session_variables['logout'] = '';
+      // Add the default toolbar links to the session variables
+      $this->session_variables = $toolbar_links;
 
       if ($this->hasCookieConsent()) {
+
+        // Get the user session and reset the session_variables
         $Session = $this->_getSession();
+
+        // Add the toolbar links back to the session variables
+        $this->session_variables = $toolbar_links;
+
+        // Get friends
         $Friend = $Session->getFriend();
+
         if ($Session->isLoggedIn()) {
-          $this->session_variables['user_ldap_uid'] = $Friend->getUID();
-          $this->session_variables['name'] = $Friend->getFirstName();
-          $this->session_variables['last_name'] = $Friend->getLastName();
-          $this->session_variables['full_name'] = $this->App->checkPlain($this->session_variables['name'] . ' ' . $this->session_variables['last_name']);
-          $this->session_variables['create_account_link'] = 'Welcome, ' . $this->session_variables['full_name'];
-          if (!empty($this->session_variables['user_ldap_uid'])){
-             $this->session_variables['create_account_link'] = '<a href="https://www.eclipse.org/user/' . $this->session_variables['user_ldap_uid'] . '">Welcome, ' . $this->session_variables['full_name'] . '</a>';
+          $this->session_variables['user_login'] = "";
+          $user_name = 'Anonymous';
+          if (!$first_name = $Friend->getFirstName() && !$last_name = $Friend->getLastName()) {
+            $user_name = $Friend->getFirstName() . ' ' . $Friend->getLastName();
+            $user_name = htmlspecialchars($user_name, ENT_QUOTES, 'UTF-8');
           }
-          $this->session_variables['my_account_link'] = '<a href="' . $this->getBaseUrlLogin() . '/user/edit" class="" data-tab-destination="tab-profile"><i class="fa fa-edit fa-fw"></i> Edit my account</a>';
+          $this->session_variables['dropdown'] = 'Welcome, ' . $user_name;
+          $this->session_variables['manage_account'] = '<a href="https://www.eclipse.org/user/' . $Friend->getUID() . '"><i class="fa fa-user"></i> View Profile</a>';
+          $this->session_variables['view_account'] = '<a href="' . $this->getBaseUrlLogin() . '/user/edit" class="" data-tab-destination="tab-profile"><i class="fa fa-edit"></i> Edit Profile</a>';
+          $this->session_variables['manage_cookies'] = '<a class="toolbar-manage-cookies dropdown-toggle"><i class="fa fa-wrench"></i> Manage Cookies</a>';
           // Adding <li> with logout because we only display
           // two options if the user is not logged in.
-          $this->session_variables['logout'] = '<li><a href="' . $this->getBaseUrlLogin() . '/user/logout"><i class="fa fa-power-off fa-fw"></i> Log out</a></li>';
+          $this->session_variables['logout'] = '<li class="divider"></li><li><a href="' . $this->getBaseUrlLogin() . '/user/logout"><i class="fa fa-sign-out"></i> Log out</a></li>';
         }
       }
     }
@@ -2188,6 +2396,23 @@
       $this->setAttributes('body', 'hidden-cfa-button');
     }
 
+    // Generate caching headers
+    if ($this->App->getPreventCaching()) {
+      $ts = gmdate("D, d M Y H:i:s") . " GMT";
+      header("Cache-Control: no-cache, must-revalidate");
+      header("Pragma: no-cache");
+      header("Last-Modified: ". $ts);
+      header("Expires:" . $ts);
+    }
+    else{
+      // 15 minute caching for html php pages
+      $caching_seconds = 900;
+      $ts = gmdate("D, d M Y H:i:s", time() + $caching_seconds) . " GMT";
+      header("Expires:" . $ts);
+      header("Pragma: cache");
+      header("Cache-Control: max-age=" . $caching_seconds);
+    }
+
     ob_start();
     switch ($this->getLayout()) {
       case 'barebone':
@@ -2418,15 +2643,30 @@
     if (!$this->getDisplayToolbar()) {
       return "";
     }
+
+    $more_links = '<li>'. $this->getSessionVariables('manage_cookies') .'</li>';
+    $dropdown = $this->getSessionVariables('dropdown');
+    if (!empty($dropdown)) {
+      $more_links = '<li class="dropdown">
+                <a href="#" class="dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'. $this->getSessionVariables('dropdown') .' <span class="caret"></span></a>
+                <ul class="dropdown-menu toolbar-dropdown-menu" aria-labelledby="dropdownMenu1">
+                  <li>'. $this->getSessionVariables('manage_account') .'</li>
+                  <li>'. $this->getSessionVariables('view_account') .'</li>
+                  <li class="divider"></li>
+                  <li>'. $this->getSessionVariables('manage_cookies') .'</li>
+                  '.$this->getSessionVariables('logout').'
+                </ul>
+              </li>';
+    }
+
     return <<<EOHTML
     <div{$this->getAttributes("toolbar-container-wrapper")}>
       <div{$this->getAttributes("toolbar-container")}>
         <div{$this->getAttributes("toolbar-row")}>
           <div{$this->getAttributes("toolbar-user-links")}>
             <ul class="list-inline">
-              <li>{$this->getSessionVariables('create_account_link')}</li>
-              <li>{$this->getSessionVariables('my_account_link')}</li>
-              {$this->getSessionVariables('logout')}
+              {$this->getSessionVariables('user_login')}
+              {$more_links}
             </ul>
           </div>
           {$this->getToolbarLeftContent()}
@@ -2630,17 +2870,8 @@
    * @return string
    */
   public function getRandomPromo($frontpage = FALSE){
-    include_once ($_SERVER['DOCUMENT_ROOT'] . "/membership/promo/promos.php");
-    if (!function_exists('chooseRandomPromo')) {
-      return '';
-    }
-
-    $ad_id = null;
-    if (isset($_GET['ad_id']) && ctype_digit($_GET['ad_id'])) {
-      $ad_id = $_GET['ad_id'];
-    }
-
-    return chooseRandomPromo($ad_id, $frontpage);
+    include_once(realpath(dirname(__FILE__) . '/../ads/promotions.class.php'));
+    return Promotions::output();
   }
 
   /**
diff --git a/eclipse.org-common/classes/themes/eclipse_ide.class.php b/eclipse.org-common/classes/themes/eclipse_ide.class.php
index 29d54ee..232c807 100644
--- a/eclipse.org-common/classes/themes/eclipse_ide.class.php
+++ b/eclipse.org-common/classes/themes/eclipse_ide.class.php
@@ -33,7 +33,6 @@
 
 
     $this->removeAttributes('featured-footer', 'background-secondary');
-    $this->setAttributes('featured-footer', 'background-tertiary');
 
   }
 }
diff --git a/eclipse.org-common/classes/themes/quicksilver.class.php b/eclipse.org-common/classes/themes/quicksilver.class.php
index ad60275..2123478 100644
--- a/eclipse.org-common/classes/themes/quicksilver.class.php
+++ b/eclipse.org-common/classes/themes/quicksilver.class.php
@@ -28,11 +28,9 @@
     $this->resetAttributes('main-sidebar');
 
     $this->setAttributes('header-left', 'col-sm-5 col-md-4');
-    $this->setAttributes('main-menu-wrapper', 'col-sm-15 col-md-15 reset margin-top-10');
+    $this->setAttributes('main-menu-wrapper', 'col-sm-19 col-md-20 margin-top-10');
     $this->setAttributes('main-menu-wrapper-no-header-right', 'col-sm-24 col-md-19 reset margin-top-10');
-    $this->setAttributes('header-right', 'col-sm-4 col-md-5 text-right hidden-print hidden-xs pull-right margin-top-10');
 
-    $this->setAttributes('navbar-main-menu', 'float-right');
     $this->removeAttributes('main', 'no-promo');
     $this->setAttributes('breadcrumbs', 'breadcrumbs-default-margin');
     $this->setAlternateLayout();
@@ -41,10 +39,14 @@
     $this->setAttributes('img_logo_mobile', '160', 'width');
 
     // Featured footer
-    $this->setAttributes('featured-footer', 'featured-footer featured-footer-newsletter background-secondary');
+    $this->setAttributes('featured-footer', 'featured-footer featured-footer-newsletter');
 
     // Set attributes on main sidebar
     $this->setAttributes('main-sidebar', 'main-sidebar-default-margin');
+
+    $this->setAttributes('btn-call-for-action', 'float-right hidden-xs');
+    $this->setAttributes('main-menu', 'float-sm-right');
+    $this->removeAttributes('navbar-main-menu', 'reset');
   }
 
   public function setAlternateLayout($enable = FALSE) {
@@ -71,26 +73,10 @@
    * Hide headerRight div if empty
    *
    * {@inheritDoc}
-   * @see BaseTheme::_getHeaderRight()
+   * @see BaseTheme::getHeaderRight()
    */
   public function getHeaderRight(){
-    $cfa_button = $this->getCfaButton();
-    if (!$this->getDisplayHeaderRight() || empty($cfa_button)) {
-      $this->setDisplayHeaderRight(FALSE);
-      $this->resetAttributes('main-menu-wrapper');
-      $this->setAttributes('main-menu-wrapper', 'col-sm-19 col-md-20 reset');
-
-      if (strtolower($this->getLayout()) !== 'barebone') {
-        $this->setAttributes('main-menu-wrapper', 'margin-top-10');
-      }
-      return "";
-    }
-
-   return <<<EOHTML
-      <div{$this->getAttributes('header-right')}>
-        {$this->getCfaButton()}
-      </div>
-EOHTML;
+   return "";
   }
 
   /**
@@ -120,11 +106,20 @@
   }
 
   /**
+   * Get Menu Prefix
+   *
+   * @return string
+   */
+  public function getMainMenuPrefix() {
+    return $this->getCfaButton();
+  }
+
+  /**
    * Get Menu Suffix
    *
    * @return string
    */
-  protected function _getMenuSuffix(){
+  public function getMenuSuffix(){
     $suffix_items = array();
 
     $google_search = $this->getGoogleSearch();
@@ -159,40 +154,6 @@
    * @see BaseTheme::getFooterPrexfix()
    */
   public function getFooterPrexfix() {
-    $main_container_col = "col-sm-24";
-    $promo_html = "";
-
-    include_once ($_SERVER['DOCUMENT_ROOT'] . "/membership/promo/promos.php");
-    if (function_exists('getFoundationPromos') && function_exists('buildStrategicAd')) {
-      $foundation_promo = getFoundationPromos();
-      if (!empty($foundation_promo)) {
-        $main_container_col = "col-sm-10 col-sm-offset-3 margin-bottom-20";
-        $foundation_promo = reset($foundation_promo);
-        $promo_html = '<div class="col-sm-8">' . buildStrategicAd($foundation_promo) . '</div>';
-      }
-    }
-
-    return <<<EOHTML
-    <!-- Sign Up to our Newsletter -->
-    <div{$this->getAttributes('featured-footer')}>
-      <div class="container">
-        <div class="row">
-          <div class="{$main_container_col}">
-            <p><i data-feather="mail" stroke-width="1"></i></p>
-            <h2>Sign up to our Newsletter</h2>
-            <p>A fresh new issue delivered monthly</p>
-            <form action="https://eclipsecon.us6.list-manage.com/subscribe/post" method="post" target="_blank">
-              <div class="form-group">
-                <input type="hidden" name="u" value="eaf9e1f06f194eadc66788a85">
-                <input type="hidden" name="id" value="46e57eacf1">
-              </div>
-              <input type="submit" value="Subscribe" name="subscribe" class="button btn btn-warning">
-            </form>
-          </div>
-          {$promo_html}
-        </div>
-      </div>
-    </div>
-EOHTML;
+    return $this->getFeaturedStoryFooter();
   }
-}
+}
\ No newline at end of file
diff --git a/eclipse.org-common/classes/themes/solstice.class.php b/eclipse.org-common/classes/themes/solstice.class.php
index e988348..dd357ae 100644
--- a/eclipse.org-common/classes/themes/solstice.class.php
+++ b/eclipse.org-common/classes/themes/solstice.class.php
@@ -30,6 +30,36 @@
     $this->setAttributes('footer2', 'col-sm-6 hidden-print');
     $this->setAttributes('footer3', 'col-sm-6 hidden-print');
     $this->setAttributes('footer4', 'col-sm-6 hidden-print');
+
+    // Footer links
+    $this->setFooterLinks("about_us", "About Us", $this->getBaseUrl() . "org/", "region_1", 1);
+    $this->setFooterLinks("contact_us", "Contact Us", $this->getBaseUrl() . "org/foundation/contact.php", "region_1", 2);
+    $this->setFooterLinks("donate", "Donate", $this->getBaseUrl() . "donate", "region_1", 3);
+    $this->setFooterLinks("members", "Members", $this->getBaseUrl() . "membership/", "region_1", 4);
+    $this->setFooterLinks("governance", "Governance", $this->getBaseUrl() . "org/documents/", "region_1", 5);
+    $this->setFooterLinks("code_of_conduct", "Code of Conduct", $this->getBaseUrl() . "org/documents/Community_Code_of_Conduct.php", "region_1", 6);
+    $this->setFooterLinks("logo_and_artwork", "Logo and Artwork", $this->getBaseUrl() . "artwork/", "region_1", 7);
+    $this->setFooterLinks("board_of_directors", "Board of Directors", $this->getBaseUrl() . "org/foundation/directors.php", "region_1", 8);
+
+    $this->setFooterLinks("privary_policy", "Privacy Policy", $this->getBaseUrl() . "legal/privacy.php", "region_2", 1);
+    $this->setFooterLinks("terms_of_use", "Terms of Use", $this->getBaseUrl() . "legal/termsofuse.php", "region_2", 2);
+    $this->setFooterLinks("copyright_agent", "Copyright Agent", $this->getBaseUrl() . "legal/copyright.php", "region_2", 3);
+    $this->setFooterLinks("epl", "Eclipse Public License", $this->getBaseUrl() . "legal/epl-2.0/", "region_2", 4);
+    $this->setFooterLinks("legal_resources", "Legal Resources", $this->getBaseUrl() . "legal/", "region_2", 5);
+
+    $this->setFooterLinks("report_a_bug", "Report a Bug", "https://bugs.eclipse.org/bugs/", "region_3", 1);
+    $this->setFooterLinks("documentation", "Documentation", "//help.eclipse.org/", "region_3", 2);
+    $this->setFooterLinks("contribute", "How to Contribute", $this->getBaseUrl() . "contribute/", "region_3", 3);
+    $this->setFooterLinks("mailing_lists", "Mailing Lists", $this->getBaseUrl() . "mail/", "region_3", 4);
+    $this->setFooterLinks("forums", "Forums", $this->getBaseUrl() . "forums/", "region_3", 5);
+    $this->setFooterLinks("marketplace", "Marketplace", "//marketplace.eclipse.org", "region_3", 6);
+
+    $this->setFooterLinks("ide_and_tools", "IDE and Tools", $this->getBaseUrl() . "ide/", "region_4", 1);
+    $this->setFooterLinks("projects", "Projects", $this->getBaseUrl() . "projects", "region_4", 2);
+    $this->setFooterLinks("working_groups", "Working Groups", $this->getBaseUrl() . "org/workinggroups/", "region_4", 3);
+    $this->setFooterLinks("research", "Research@Eclipse", $this->getBaseUrl() . "org/research/", "region_4", 4);
+    $this->setFooterLinks("security", "Report a Vulnerability", $this->getBaseUrl() . "security/", "region_4", 5);
+    $this->setFooterLinks("service_status", "Service Status", "https://status.eclipse.org", "region_4", 6);
   }
 
   /**
@@ -38,14 +68,7 @@
   public function getFooterRegion1() {
     return <<<EOHTML
     <h2 class="section-title">Eclipse Foundation</h2>
-    <ul class="nav">
-    <li><a href="{$this->getBaseUrl()}org/">About Us</a></li>
-    <li><a href="{$this->getBaseUrl()}org/foundation/contact.php">Contact Us</a></li>
-    <li><a href="{$this->getBaseUrl()}donate">Donate</a></li>
-      <li><a href="{$this->getBaseUrl()}org/documents/">Governance</a></li>
-      <li><a href="{$this->getBaseUrl()}artwork/">Logo and Artwork</a></li>
-      <li><a href="{$this->getBaseUrl()}org/foundation/directors.php">Board of Directors</a></li>
-    </ul>
+    {$this->getFooterLinks('region_1')}
 EOHTML;
   }
 
@@ -55,13 +78,7 @@
   public function getFooterRegion2() {
     return <<<EOHTML
     <h2 class="section-title">Legal</h2>
-    <ul class="nav">
-      <li><a href="{$this->getBaseUrl()}legal/privacy.php">Privacy Policy</a></li>
-      <li><a href="{$this->getBaseUrl()}legal/termsofuse.php">Terms of Use</a></li>
-      <li><a href="{$this->getBaseUrl()}legal/copyright.php">Copyright Agent</a></li>
-      <li><a href="{$this->getBaseUrl()}legal/epl-2.0/">Eclipse Public License</a></li>
-      <li><a href="{$this->getBaseUrl()}legal/">Legal Resources </a></li>
-    </ul>
+    {$this->getFooterLinks('region_2')}
 EOHTML;
   }
 
@@ -71,14 +88,7 @@
   public function getFooterRegion3() {
     return <<<EOHTML
     <h2 class="section-title">Useful Links</h2>
-    <ul class="nav">
-      <li><a href="https://bugs.eclipse.org/bugs/">Report a Bug</a></li>
-      <li><a href="//help.eclipse.org/">Documentation</a></li>
-      <li><a href="{$this->getBaseUrl()}contribute/">How to Contribute</a></li>
-      <li><a href="{$this->getBaseUrl()}mail/">Mailing Lists</a></li>
-      <li><a href="{$this->getBaseUrl()}forums/">Forums</a></li>
-      <li><a href="//marketplace.eclipse.org">Marketplace</a></li>
-    </ul>
+    {$this->getFooterLinks('region_3')}
 EOHTML;
   }
 
@@ -88,13 +98,7 @@
   public function getFooterRegion4() {
     return <<<EOHTML
     <h2 class="section-title">Other</h2>
-    <ul class="nav">
-      <li><a href="{$this->getBaseUrl()}ide/">IDE and Tools</a></li>
-      <li><a href="{$this->getBaseUrl()}projects">Community of Projects</a></li>
-      <li><a href="{$this->getBaseUrl()}org/workinggroups/">Working Groups</a></li>
-      <li><a href="{$this->getBaseUrl()}org/research/">Research@Eclipse</a></li>
-      <li><a href="https://status.eclipse.org">Service Status</a></li>
-    </ul>
+    {$this->getFooterLinks('region_4')}
 EOHTML;
   }
 
@@ -117,12 +121,6 @@
                 </a>
               </li>
               <li>
-                <a class="social-media-link fa-stack fa-lg" href="https://plus.google.com/+Eclipse">
-                  <i class="fa fa-circle-thin fa-stack-2x"></i>
-                  <i class="fa fa-google-plus fa-stack-1x"></i>
-                </a>
-              </li>
-              <li>
                 <a class="social-media-link fa-stack fa-lg" href="https://www.facebook.com/eclipse.org">
                   <i class="fa fa-circle-thin fa-stack-2x"></i>
                   <i class="fa fa-facebook fa-stack-1x"></i>
diff --git a/eclipse.org-common/classes/users/infraBlock.class.php b/eclipse.org-common/classes/users/infraBlock.class.php
index a4b635d..a1dad65 100644
--- a/eclipse.org-common/classes/users/infraBlock.class.php
+++ b/eclipse.org-common/classes/users/infraBlock.class.php
@@ -49,7 +49,7 @@
    */
   public function isBlocked(){
     $rvalue = FALSE;
-    $subnet = $_SERVER['REMOTE_ADDR'];
+    $subnet = $this->App->getRemoteIPAddress();
     //test if we have something that looks like an ip
     if ( preg_match('/[1-9]{1,3}\.(([0-9]{1,3}\.?){3})/', $subnet )) {
       if ($this->IsCommitter) {
diff --git a/eclipse.org-common/system/app.class.php b/eclipse.org-common/system/app.class.php
index e90b381..d5fce27 100644
--- a/eclipse.org-common/system/app.class.php
+++ b/eclipse.org-common/system/app.class.php
@@ -1,19 +1,20 @@
 <?php
 /**
- * *****************************************************************************
- * Copyright (c) 2006-2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+ * ********************************************************************
+ * Copyright (c) 2006-2020 Eclipse Foundation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
  *
  * Contributors:
  * Denis Roy (Eclipse Foundation)- initial API and implementation
  * Karl Matthias (Eclipse Foundation) - Database access management
  * Christopher Guindon (Eclipse Foundation)
- * *****************************************************************************
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * ********************************************************************
  */
-
 class App {
 
   /**
@@ -56,14 +57,14 @@
    *
    * @var string
    */
-  private $OUR_DOWNLOAD_URL = "http://download1.eclipse.org";
+  private $OUR_DOWNLOAD_URL = "https://download.eclipse.org";
 
   /**
    * Public download URL
    *
    * @var string
    */
-  private $PUB_DOWNLOAD_URL = "http://download.eclipse.org";
+  private $PUB_DOWNLOAD_URL = "https://download.eclipse.org";
 
   /**
    * Download base path
@@ -159,7 +160,7 @@
    *
    * @var string
    */
-  private $OGDescription = "The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects, including runtimes, tools and frameworks.";
+  private $OGDescription = "The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 375 open source projects, including runtimes, tools and frameworks.";
 
   /**
    * Open Graph Protocol image
@@ -225,6 +226,14 @@
    */
   private $OutDatedMsg = "";
 
+
+  /**
+   * Prevent caching flag
+   *
+   * @var bool
+   */
+  private $prevent_caching = FALSE;
+
   /**
    * Development mode flag
    *
@@ -260,6 +269,13 @@
    */
   private $Messages = NULL;
 
+  /**
+   * Sessions()
+   *
+   * @var unknown
+   */
+  private $Session = NULL;
+
   // Default constructor
   function __construct() {
 
@@ -299,6 +315,26 @@
   }
 
   /**
+   * Anonymize IP adress
+   *
+   * @param string $ip
+   *
+   * @return string|NULL
+   */
+  function anonymizeIP($ip = NULL) {
+    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+      $ip = explode('.', $ip, -1);
+      return implode('.', $ip) . ".0";
+    }
+
+    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
+      $ip = explode(':', $ip, -1);
+      return implode(':', $ip) . ".0";
+    }
+    return NULL;
+  }
+
+  /**
    * Encodes special characters in a plain-text string for display as HTML.
    *
    * @param string $text
@@ -309,6 +345,18 @@
   }
 
   /**
+   * Verify if consent was given to use cookies
+   *
+   * @return boolean
+   */
+  public function hasCookieConsent() {
+    if (isset($_COOKIE['eclipse_cookieconsent_status']) && $_COOKIE['eclipse_cookieconsent_status'] === 'allow') {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
    * Returns the Webmaster object
    *
    * @return object
@@ -695,15 +743,17 @@
    *
    * @return string
    */
-  function getRemoteIPAddress() {
-    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
-      return $_SERVER['HTTP_CLIENT_IP'];
-    }
-    else
-      if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
-        return $_SERVER['HTTP_X_FORWARDED_FOR'];
+  function getRemoteIPAddress($ignore_forwarded_for = FALSE) {
+    $remote_addr = $_SERVER['REMOTE_ADDR'];
+
+    # If the request comes from a reverse proxy, take the last element in the list
+    if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && !$ignore_forwarded_for) {
+      $IPs = array_values(array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
+      if(preg_match('/^\d+\.\d+\.\d+\.\d+$/', trim(end($IPs)))) {
+        $remote_addr = trim(end($IPs));
       }
-    return $_SERVER['REMOTE_ADDR'];
+    }
+    return $remote_addr;
   }
 
   /**
@@ -747,13 +797,29 @@
     if (session_id() == '') {
       session_start();
     }
-    header("Cache-Control: no-store, no-cache, private, must-revalidate, max-age=0, max-stale=0");
-    header("Cache-Control: post-check=0, pre-check=0", FALSE);
-    header("Pragma: no-cache");
-    header("Expires: 0");
+    $this->prevent_caching = TRUE;
   }
 
   /**
+   * Get Prevent Caching Flag
+   *
+   * @return boolean
+   */
+  function getPreventCaching() {
+    if ($this->prevent_caching) {
+      return TRUE;
+    }
+    $Session = $this->useSession();
+    $gid = $Session->getGID();
+    if (!empty($gid)) {
+      $this->prevent_caching = TRUE;
+    }
+
+    return $this->prevent_caching;
+  }
+
+
+  /**
    * Get Alpha code
    *
    * @param unknown $_NumChars
@@ -1442,11 +1508,15 @@
    */
   function useSession($required = "") {
     require_once ($this->getBasePath() . "/system/session.class.php");
-    $ssn = new Session(); // constructor calls validate
-    if ($ssn->getGID() == "" && $required == "required") {
-      $ssn->redirectToLogin();
+    if ($this->Session instanceof Session) {
+      return $this->Session;
     }
-    return $ssn;
+
+    $this->Session = new Session(); // constructor calls validate
+    if ($this->Session->getGID() == "" && $required == "required") {
+      $this->Session->redirectToLogin();
+    }
+    return $this->Session;
   }
 
   /**
@@ -1788,6 +1858,18 @@
   }
 
   /**
+   * @author droy
+   * @since 2018-11-09
+   * @param bool ignoreForwardedFor
+   *
+   * @deprecated
+   * @return string Client IP address
+   */
+  function getClientRealIP($ignore_forwarded_for = FALSE) {
+    return $this->getRemoteIPAddress($ignore_forwarded_for);
+  }
+
+  /**
    * Set Promotion Path
    *
    * @param unknown $_path
@@ -1795,19 +1877,6 @@
   function setPromotionPath($_path) {
     $this->CustomPromotionPath = $_SERVER['DOCUMENT_ROOT'] . $_path;
   }
-
-  /**
-   * Use reCAPTCHA service
-   *
-   * @param bool $ssl
-   *
-   * @return Captcha
-   */
-  public function useCaptcha($ssl = true) {
-    include_once ($this->getBasePath() . '/classes/captcha/captcha.class.php');
-    return new Captcha($ssl);
-  }
-
   /**
    * Record a database record
    *
@@ -1852,6 +1921,7 @@
     $this->setDatabase("epic", "localhost", "dashboard", "draobhsad", "epic_demo");
     $this->setDatabase("conferences", "localhost", "dashboard", "draobhsad", "conferences_demo");
     $this->setDatabase("marketplace", "localhost", "dashboard", "draobhsad", "marketplace_demo");
+    $this->setDatabase("dashboard", "localhost", "dashboard", "draobhsad", "dashboard_demo");
 
     // Production Databases
     $this->set("bugzilla_db_classfile_ro", 'dbconnection_bugs_ro.class.php');
@@ -2030,6 +2100,13 @@
       if ($this->devmode || $this->logsql) {
         $this->SQLBacktrace();
       }
+      # capture and flush the buffer
+      $html = ob_get_contents();
+      ob_end_clean();
+      header('HTTP/1.1 500 Internal Server Error');
+
+      # Send the error to the screen. This may not be desirable
+      echo $html;
       exit();
     }
   }
diff --git a/eclipse.org-common/system/breadcrumbs.class.php b/eclipse.org-common/system/breadcrumbs.class.php
index a68098c..39ed97e 100644
--- a/eclipse.org-common/system/breadcrumbs.class.php
+++ b/eclipse.org-common/system/breadcrumbs.class.php
@@ -44,8 +44,10 @@
     "donate" => "Donate",
     "downloads" => "Downloads",
     "eclipse4" => "Eclipse SDK 4.x",
+    "eclipseide" => "Eclipse IDE",
     "errors" => "Errors",
     "europa" => "Europa",
+    "europe" => "Europe",
     "friends" => "Friends of Eclipse",
     "galileo" => "Galileo",
     "ganymede" => "Ganymede",
diff --git a/eclipse.org-common/system/eclipseenv.class.php b/eclipse.org-common/system/eclipseenv.class.php
index a1fe924..bd33cbe 100644
--- a/eclipse.org-common/system/eclipseenv.class.php
+++ b/eclipse.org-common/system/eclipseenv.class.php
@@ -83,10 +83,11 @@
     // @todo: allowed_hosts is deprecated
     $server['dev'] = array(
       'shortname' => 'local',
-      'cookie' => '.eclipse.local',
+      'cookie' => '.dev.docker',
       'domain' => 'www.eclipse.php53.dev.docker',
       'dev_domain' => 'dev_eclipse.php53.dev.docker',
       'accounts' => 'accounts.php55.dev.docker',
+      'api' => 'api.php55.dev.docker',
       'allowed_hosts' => array(
         'eclipse.local',
         'www.eclipse.local',
@@ -102,6 +103,7 @@
       // We currently dont have a staging server for dev.eclipse.org
       'dev_domain' => 'dev.eclipse.org',
       'accounts' => 'accounts-staging.eclipse.org',
+      'api' => 'api-staging.eclipse.org',
       'allowed_hosts' => array(
         'staging.eclipse.org'
       ),
@@ -113,6 +115,7 @@
       'domain' => 'www.eclipse.org',
       'dev_domain' => 'dev.eclipse.org',
       'accounts' => 'accounts.eclipse.org',
+      'api' => 'api.eclipse.org',
       'allowed_hosts' => array(
         // Empty, since it's the default.
       ),
diff --git a/eclipse.org-common/system/session.class.php b/eclipse.org-common/system/session.class.php
index f609d92..3ef65c6 100644
--- a/eclipse.org-common/system/session.class.php
+++ b/eclipse.org-common/system/session.class.php
@@ -28,8 +28,6 @@
 
   private $updated_at = "";
 
-  private $is_persistent = 0;
-
   private $Friend = NULL;
 
   private $data = "";
@@ -40,10 +38,10 @@
 
   private $env = "";
 
-  private $htaccess = "";
-
   private $login_page = "";
 
+  private $cookies_sent = FALSE;
+
   /**
    * Default constructor
    *
@@ -52,12 +50,10 @@
   public function __construct($persistent=0, $configs = array()) {
    $this->App = new App();
    $domain = $this->App->getEclipseDomain();
-
-    $default = array(
+   $default = array(
       'domain' => $domain['cookie'] ,
       'session_name' => 'ECLIPSESESSION',
       'env' => 'ECLIPSE_ENV',
-      'htaccess' => '/home/data/httpd/friends.eclipse.org/html/.htaccess',
       'login_page' => 'https://' . $domain['accounts'] . '/user/login',
     );
 
@@ -70,7 +66,6 @@
     }
 
     $this->validate();
-    $this->setIsPersistent($persistent);
   }
 
   function getGID() {
@@ -101,7 +96,10 @@
   }
 
   function getIsPersistent() {
-    return $this->is_persistent == NULL ? 0 : $this->is_persistent;
+    if ($this->hasCookieConsent()) {
+      return 1;
+    }
+    return 0;
   }
 
   function getLoginPageURL() {
@@ -112,6 +110,17 @@
     return $this->getGID() !== "";
   }
 
+  /**
+   * Verify if consent was given to use cookies
+   *
+   * @return boolean
+   */
+  public function hasCookieConsent() {
+    $App = new App();
+    return $App->hasCookieConsent();
+  }
+
+
   function setGID($_gid) {
     $this->gid = $_gid;
   }
@@ -138,8 +147,13 @@
     $this->data = serialize($_data);
   }
 
+  /**
+   * Set is_persistent
+   *
+   * @deprecated
+   */
   function setIsPersistent($_is_persistent) {
-    $this->is_persistent = $_is_persistent;
+    trigger_error("Deprecated function called.", E_USER_NOTICE);
   }
 
   /**
@@ -150,13 +164,7 @@
   function validate() {
     $cookie = (isset($_COOKIE[$this->session_name]) ? $_COOKIE[$this->session_name] : "");
     $rValue = FALSE;
-    if ((!$this->load($cookie))) {
-      # Failed - no such session, or session no match.  Need to relogin
-      # Bug 257675
-      # setcookie($this->session_name, "", time() - 3600, "/", $this->domain);
-      $rValue = FALSE;
-    }
-    else {
+    if ($this->load($cookie)) {
       # TODO: update session?
       $rValue = TRUE;
       $this->maintenance();
@@ -181,15 +189,15 @@
     # Should these also be in session() ?
     setcookie("TAKEMEBACK", "", 0, "/", ".eclipse.org");
     setcookie("fud_session_2015", "", 0, "/forums/", ".eclipse.org");
-    setcookie($this->session_name, "", time() - 3600, "/", $this->domain, 1, TRUE);
-    setcookie($this->env, "", time() - 3600, "/", $this->domain, 0, TRUE);
+    setcookie($this->session_name, "", 0, "/", $this->domain, 1, TRUE);
+    setcookie($this->env, "", 0, "/", $this->domain, 0, TRUE);
 
     if (!$App->devmode) {
       # Log this event
       $EvtLog = new EvtLog();
       $EvtLog->setLogTable("sessions");
       $EvtLog->setPK1($Friend->getBugzillaID());
-      $EvtLog->setPK2($_SERVER['REMOTE_ADDR']);
+      $EvtLog->setPK2($App->getRemoteIPAddress());
       $EvtLog->setLogAction("DELETE");
       $EvtLog->insertModLog("apache");
     }
@@ -237,43 +245,46 @@
         $EvtLog = new EvtLog();
         $EvtLog->setLogTable("sessions");
         $EvtLog->setPK1($Friend->getBugzillaID());
-        $EvtLog->setPK2($_SERVER['REMOTE_ADDR']);
+        $EvtLog->setPK2($App->getRemoteIPAddress());
         $EvtLog->setLogAction("INSERT");
         $EvtLog->insertModLog("apache");
-
-        # add session to the .htaccess file
-        # TODO: implement a smart locking
-        if ($Friend->getIsBenefit() && is_writable($this->htaccess)) {
-          $fh = fopen($this->htaccess, 'a') or die("can't open file");
-          $new_line = "SetEnvIf Cookie \"" . $this->getGID() . "\" eclipsefriend=1\n";
-          fwrite($fh, $new_line);
-          fclose($fh);
-        }
       }
-
-      $cookie_time = 0;
-      if ($this->getIsPersistent()) {
-        $cookie_time = time()+3600*24*365;
-      }
-
-      setcookie($this->session_name, $this->getGID(), $cookie_time, "/", $this->domain, 1, TRUE);
-
-      # 422767 Session broken between http and https
-      # Set to "S" for Secure.  We could eventually append more environment data, separated by semicolons and such
-      setcookie($this->env, "S", $cookie_time, "/", $this->domain, 0, TRUE);
-
+      $this->setEclipseSessionCookies();
     }
   }
 
+  /**
+   * Set Eclipse Session Cookies
+   *
+   * @return boolean
+   */
+  public function setEclipseSessionCookies(){
+    $gid = $this->getGID();
+    if (empty($gid) || $this->cookies_sent) {
+      return FALSE;
+    }
+    $this->cookies_sent = TRUE;
+    $cookie_time = 0;
+    if ($this->getIsPersistent()) {
+      $cookie_time = time()+3600*24*7;
+    }
+
+    setcookie($this->session_name, $this->getGID(), $cookie_time, "/", $this->domain, 1, TRUE);
+    # 422767 Session broken between http and https
+    # Set to "S" for Secure.  We could eventually append more environment data, separated by semicolons and such
+    setcookie($this->env, "S", $cookie_time, "/", $this->domain, 0, TRUE);
+    return TRUE;
+  }
+
   function load($_gid) {
     # need to have a bugzilla ID to log in
     $rValue = FALSE;
-    if ($_gid != "") {
+    if (!empty($_gid)) {
       $App = new App();
       $sql = "SELECT /* USE MASTER */ gid, bugzilla_id, subnet, updated_at, data,  is_persistent
         FROM sessions
-        WHERE gid = " . $App->returnQuotedString($App->sqlSanitize($_gid, NULL));
-        # " AND subnet = " . $App->returnQuotedString($this->getClientSubnet());
+        WHERE gid = " . $App->returnQuotedString($App->sqlSanitize($_gid, NULL)) . "
+        AND subnet = " . $App->returnQuotedString($this->getClientSubnet());
 
       $result = $App->eclipse_sql($sql);
       if ($result && mysql_num_rows($result) > 0) {
@@ -284,11 +295,11 @@
         $this->setSubnet($myrow['subnet']);
         $this->setUpdatedAt($myrow['updated_at']);
         $this->data = $myrow['data'];
-        $this->setIsPersistent($myrow['is_persistent']);
 
         # touch this session
-        $sql = "UPDATE sessions SET updated_at = NOW() WHERE gid = '" . $App->sqlSanitize($_gid, NULL) . "'";
+        $sql = "UPDATE sessions SET updated_at = NOW(), is_persistent = '" . $App->sqlSanitize($this->getIsPersistent(), NULL) . "' WHERE gid = '" . $App->sqlSanitize($_gid, NULL) . "'";
         $App->eclipse_sql($sql);
+        $this->setEclipseSessionCookies();
       }
     }
     return $rValue;
@@ -296,46 +307,15 @@
 
   function maintenance() {
     $App = new App();
-
-    $sql = "DELETE FROM sessions
-      WHERE (updated_at < DATE_SUB(NOW(), INTERVAL 7 DAY) AND is_persistent = 0)
-      OR updated_at < DATE_SUB(NOW(), INTERVAL 1 YEAR)";
-
+    // Sessions are re-generated by visiting accounts.eclipse.org
+    $sql = "DELETE FROM sessions WHERE updated_at < DATE_SUB(NOW(), INTERVAL 8 DAY)";
     $App->eclipse_sql($sql);
-
-    # 1/500 of each maintenance calls will perform htaccess cleanup
-    if (rand(0, 500) < 1) {
-      $this->regenrate_htaccess();
-    }
-  }
-
-  private function regenrate_htaccess() {
-    $App = new App();
-
-    if (!$App->devmode) {
-
-      $sql = "SELECT gid
-        FROM sessions AS S
-        INNER JOIN friends AS F ON F.bugzilla_id = S.bugzilla_id
-        WHERE F.is_benefit = 1";
-
-      $result = $App->eclipse_sql($sql);
-      $new_file = "";
-      while ($myrow = mysql_fetch_assoc($result)) {
-        $new_file .= "SetEnvIf Cookie \"" . $myrow['gid'] . "\" eclipsefriend=1\n";
-      }
-
-      if ($new_file != "") {
-        $fh = fopen($this->htaccess, 'w') or die("can't open file");
-        fwrite($fh, $new_file);
-        fclose($fh);
-      }
-    }
   }
 
   function getClientSubnet() {
     # return class-c subnet
-    return substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], ".")) . ".0";
+    $App = new App();
+    return substr($App->getRemoteIPAddress(), 0, strrpos($App->getRemoteIPAddress(), ".")) . ".0";
   }
 
   function redirectToLogin() {
diff --git a/eclipse.org-common/themes/solstice/.gitignore b/eclipse.org-common/themes/solstice/.gitignore
index f7ff50b..a282f3b 100644
--- a/eclipse.org-common/themes/solstice/.gitignore
+++ b/eclipse.org-common/themes/solstice/.gitignore
@@ -4,3 +4,4 @@
 /app/psd
 /false/
 /npm-debug.log
+/eclipsefdn-solstice-assets
diff --git a/eclipse.org-common/themes/solstice/docs/classes.php b/eclipse.org-common/themes/solstice/docs/classes.php
deleted file mode 100644
index bded87a..0000000
--- a/eclipse.org-common/themes/solstice/docs/classes.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-
-  require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/app.class.php");
-  require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/nav.class.php");
-  require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/menu.class.php");
-
-
-  $App   = new App();
-  $Nav  = new Nav();
-  $Menu   = new Menu();
-
-  # Begin: page-specific settings.  Change these.
-  $pageTitle     = " eclipse.org-common Documentation";
-  $pageKeywords  = "eclipse eclipse.org api, eclipse.org-common";
-  $pageAuthor    = "Christopher Guindon";
-
-
-  // Place your html content in a file called content/en_pagename.php
-  ob_start();
-  include("content/en_" . $App->getScriptName());
-  $html = ob_get_clean();
-
-  $App->generatePage(NULL, $Menu, NULL, $pageAuthor, $pageKeywords, $pageTitle, $html);
-
diff --git a/eclipse.org-common/themes/solstice/docs/classes/captcha.php b/eclipse.org-common/themes/solstice/docs/classes/captcha.php
deleted file mode 100644
index 79b1fdd..0000000
--- a/eclipse.org-common/themes/solstice/docs/classes/captcha.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-?>
-<hr/>
-<h3 id="section-captcha">captcha.class.php</h3>
-<p>reCAPTCHA is a free service to protect your website from spam and abuse.
-reCAPTCHA uses an advanced risk analysis engine and adaptive CAPTCHAs to keep
-automated software from engaging in abusive activities on your site.
-It does this while letting your valid users pass through with ease.</p>
-
-<h4 id="section-recaptcha">reCAPTCHA</h4>
-<form action="" method="post">
-  <?php
-    $Captcha = $App->useCaptcha($ssl = true);
-    if ($Captcha->validate()) {
-      echo "You got it!";
-    }
-    //echo $Captcha->get_error();
-    echo $Captcha->get_html();
-  ?>
-  <br/>
-  <input type="submit" value="submit" />
-</form>
-<h5>Code</h5>
-<div class="editor" data-editor-lang="html" data-editor-no-focus="true"></div>
-<pre>
-&lt;?php
-  $Captcha = $App->useCaptcha($ssl = true);
-  if ($Captcha->validate()) {
-    echo "You got it!";
-  }
-  echo $Captcha->get_html();
-</pre>
-
-<br/>
-<h4 id="section-recaptcha-mailhide">Mailhide</h4>
-<?php ob_start();?>
-<p>The Mailhide version of example@example.com is <?php print $Captcha->get_mailhide_html("example@example.com"); ?>.</p>
-
-<p>The url for the email is:<br/>
-<a href="<?php print $Captcha->get_mailhide_url("example@example.com"); ?>" target="_blank"><?php print $Captcha->get_mailhide_url("example@example.com"); ?></a></p>
-<?php
-  $html = ob_get_clean();
-  print $html;
-?>
-
-<h5>Code</h5>
-<pre>
-&lt;?php
-  $Captcha = $App->useCaptcha($ssl = true);
-?&gt;
-
-&lt;p&gt;The Mailhide version of example@example.com is &lt?php print $Captcha->get_mailhide_html("example@example.com"); ?>.&lt;/p&gt;
-&lt;a href="&lt;?php print $Captcha->get_mailhide_url("example@example.com");?&gt;" target="_blank"&gt; &lt;?php print $Captcha->get_mailhide_url("example@example.com"); ?&gt;&lt;/a&gt;&lt;/p&gt;
-</pre>
diff --git a/eclipse.org-common/themes/solstice/docs/components/eclipsefdn-videos.php b/eclipse.org-common/themes/solstice/docs/components/eclipsefdn-videos.php
new file mode 100644
index 0000000..6dd5b72
--- /dev/null
+++ b/eclipse.org-common/themes/solstice/docs/components/eclipsefdn-videos.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright (c) 2018 Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *   Eric Poirier (Eclipse Foundation) - Initial implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+?>
+
+<h2 id="embedding-youtube-videos">Embedding Youtube videos</h2>
+
+            <div class="row">
+              <div class="col-sm-12">
+                <h3>What is the Embedding Youtube videos plugin?</h3>
+                <p>By inserting an <code>&lt;a&gt;</code> tag containing a video link in your HTML page,
+                the EclipseFdn Videos plugin will convert that tag into the iframe video if the user
+                agreed to use cookies.</p>
+                <p><strong>Note:</strong> This plugin only supports Youtube videos for now.</p>
+                <h3>Usage</h3>
+                <p><strong>With Solstice</strong></p>
+                <pre>&lt;head&gt;
+  &lt;script&gt;
+    // Use defaults
+    eclipseFdnVideos.replace();
+
+    // Customize
+    eclipseFdnVideos.replace({
+      selector: ".eclipsefdn-video",
+      resolution: "16by9",
+      cookie: {
+        name: "eclipse_cookieconsent_status",
+        value: "allow"
+      }
+    });
+  &lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;a class="eclipsefdn-video" href="https://www.youtube.com/watch?v=cnSMhgKApOg"&gt;&lt;/a&gt;
+
+  &lt;!--
+  &lt;a&gt; will be replaced with:
+  &lt;div class="eclipsefdn-video embed-responsive embed-responsive-16by9" style="height:312.1875px;"&gt;&lt;iframe src="https://www.youtube.com/embed/cnSMhgKApOg"&gt;&lt;/iframe>&lt;/div&gt;
+  --&gt;
+&lt;/body&gt;
+</pre>
+                <p><strong>Without Solstice</strong></p>
+                <p>If you are not using the Eclipse Foundation look and feel, you can still load our Embedding Youtube videos plugin like the following example:</p>
+                <pre>&lt;head&gt;
+  &lt;script src="//www.eclipse.org/eclipse.org-common/themes/solstice/public/javascript/eclipsefdn.videos.min.js"&gt;&lt;/script&gt;
+  &lt;link href="//www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/eclipsefdn-video.min.css" rel="stylesheet" type="text/css"&gt;
+
+  &lt;script&gt;
+    // Use defaults
+    eclipseFdnVideos.replace();
+
+    // Customize
+    eclipseFdnVideos.replace({
+      selector: ".eclipsefdn-video",
+      resolution: "16by9",
+      cookie: {
+        name: "eclipse_cookieconsent_status",
+        value: "allow"
+      }
+    });
+  &lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;a class="eclipsefdn-video" href="https://www.youtube.com/watch?v=cnSMhgKApOg"&gt;&lt;/a&gt;
+
+  &lt;!--
+  &lt;a&gt; will be replaced with:
+  &lt;div class="eclipsefdn-video embed-responsive embed-responsive-16by9" style="height:312.1875px;"&gt;&lt;iframe src="https://www.youtube.com/embed/cnSMhgKApOg"&gt;&lt;/iframe>&lt;/div&gt;
+  --&gt;
+&lt;/body&gt;
+</pre>
+                <p><strong>Parameters</strong></p>
+                <table class="table table-bordered">
+                  <thead>
+                    <tr>
+                      <th>Name</th>
+                      <th>Type</th>
+                      <th>Description</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    <tr>
+                      <td><code>selector</code> (optional)</td>
+                      <td>String</td>
+                      <td>By default the class <strong>"eclipsefdn-video"</strong> is being used but you can specify your own selector.</td>
+                    </tr>
+                    <tr>
+                      <td><code>resolution</code> (optional)</td>
+                      <td>String</td>
+                      <td>By default the resolution of the video is <strong>16by9</strong> but you can also choose to use the <strong>4by3</strong> resolution.
+                      Note that only these two resolutons are accepted.</td>
+                    </tr>
+                    <tr>
+                      <td><code>cookie</code> (optional)</td>
+                      <td>Object</td>
+                      <td>By default we are using the cookie name <strong>"eclipse_cookieconsent_status"</strong> and value
+                      <strong>"allow"</strong> which enables the plugin to replace the link by the iframe video only if
+                      users have given consent to use cookies. But you can choose to use your own cookie name and values.</td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+              <div class="col-sm-12">
+                <h3>Example:</h3>
+
+                <a class="eclipsefdn-video" href="https://www.youtube.com/watch?v=cnSMhgKApOg"></a>
+              </div>
+            </div>
\ No newline at end of file
diff --git a/eclipse.org-common/themes/solstice/docs/content/en_classes.php b/eclipse.org-common/themes/solstice/docs/content/en_classes.php
deleted file mode 100644
index 9504c19..0000000
--- a/eclipse.org-common/themes/solstice/docs/content/en_classes.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/*******************************************************************************
- * Copyright (c) 2014 Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Christopher Guindon (Eclipse Foundation) - Initial implementation
- *******************************************************************************/
-?>
-
-<h1><?php print $pageTitle;?></h1>
-
-<h2>Classes</h2>
-<ol>
-  <li><a href="#section-captcha">captcha.class.php</a>
-    <ul>
-      <li><a href="#section-recaptcha">reCaptcha</a></li>
-      <li><a href="#section-recaptcha-mailhide">reCaptcha mail hide</a></li>
-    </ul>
-  </li>
-</ol>
-
-<?php include('classes/captcha.php');?><hr/>
diff --git a/eclipse.org-common/themes/solstice/docs/content/en_index.php b/eclipse.org-common/themes/solstice/docs/content/en_index.php
index e04aba8..60e6d0e 100644
--- a/eclipse.org-common/themes/solstice/docs/content/en_index.php
+++ b/eclipse.org-common/themes/solstice/docs/content/en_index.php
@@ -199,9 +199,6 @@
   $Theme->setLayout($acceptable_layouts[0]);
 </pre>
 
-<h2>Eclipse.org-common Classes</h2>
-<p> Visit our <a href="classes.php">PHP classes</a> page for some documentation and example of how to use the API from eclipse.org-common.</p>
-
 <h2>CSS</h2>
 <p><a href="https://github.com/chrisguindon/solstice-assets/blob/master/stylesheets/classes.less">classes.less</a>
 and <a href="https://github.com/chrisguindon/solstice-assets/blob/master/stylesheets/fonts.less">fonts.less</a> include usefull CSS classes for
@@ -237,8 +234,10 @@
 <?php include('components/step-by-step.php');?><hr/>
 <?php include('components/timeline.php');?><hr/>
 <?php include('components/toolbar-menu.php');?><hr/>
+<?php include('components/eclipsefdn-videos.php');?><hr/>
 
 <h2 id="bootstrap">Bootstrap example</h2>
 <?php include('bootstrap/carousel.php');?><hr/>
 
 
+
diff --git a/eclipse.org-common/themes/solstice/footer.php b/eclipse.org-common/themes/solstice/footer.php
index ae01319..aed478c 100644
--- a/eclipse.org-common/themes/solstice/footer.php
+++ b/eclipse.org-common/themes/solstice/footer.php
@@ -13,7 +13,9 @@
 <p id="back-to-top">
   <a class="visible-xs" href="#top">Back to the top</a>
 </p>
-<?php print $this->getFooterPrexfix();?>
+<?php if($this->getDisplayFooterPrefix()): ?>
+  <?php print $this->getFooterPrexfix();?>
+<?php endif; ?>
 <footer<?php print $this->getAttributes('footer');?>>
   <div<?php print $this->getAttributes('footer-container');?>>
     <div class="row">
diff --git a/eclipse.org-common/themes/solstice/header.php b/eclipse.org-common/themes/solstice/header.php
index 4a6d2f9..ea07932 100644
--- a/eclipse.org-common/themes/solstice/header.php
+++ b/eclipse.org-common/themes/solstice/header.php
@@ -25,6 +25,6 @@
     <?php print $this->getScriptSettings(); ?>
   </head>
   <body<?php print $this->getAttributes('body');?>>
-    <?php //print $this->getGoogleTagManagerNoScript();?>
+    <?php print $this->getGoogleTagManagerNoScript();?>
     <a class="sr-only" href="#content">Skip to main content</a>
     <?php print $this->getHeaderTop(); ?>
diff --git a/eclipse.org-common/themes/solstice/main_menu.php b/eclipse.org-common/themes/solstice/main_menu.php
index c15921a..bc4732e 100644
--- a/eclipse.org-common/themes/solstice/main_menu.php
+++ b/eclipse.org-common/themes/solstice/main_menu.php
@@ -11,6 +11,9 @@
  *******************************************************************************/
 ?>
 <div<?php print $this->getAttributes('main-menu-wrapper');?>>
+  <?php if ($this->getMainMenuPrefix()):?>
+    <?php print $this->getMainMenuPrefix(); ?>
+  <?php endif; ?>
   <div<?php print $this->getAttributes('main-menu');?>>
     <div<?php print $this->getAttributes('navbar-main-menu');?>>
       <ul<?php print $this->getAttributes('main-menu-ul-navbar');?>>
@@ -32,8 +35,8 @@
             </ul>
           </li>
         <?php endif;?>
-        <?php if ($this->_getMenuSuffix()):?>
-          <?php print $this->_getMenuSuffix(); ?>
+        <?php if ($this->getMenuSuffix()):?>
+          <?php print $this->getMenuSuffix(); ?>
         <?php endif; ?>
 
       </ul>
diff --git a/eclipse.org-common/themes/solstice/package-lock.json b/eclipse.org-common/themes/solstice/package-lock.json
index fdb4478..7d67837 100644
--- a/eclipse.org-common/themes/solstice/package-lock.json
+++ b/eclipse.org-common/themes/solstice/package-lock.json
@@ -1,141 +1,13031 @@
 {
   "name": "eclipsefdn-eclipse.org-common",
-  "version": "0.0.0",
-  "lockfileVersion": 1,
+  "version": "0.0.1",
+  "lockfileVersion": 2,
   "requires": true,
-  "dependencies": {
-    "Yamm": {
-      "version": "github:geedmo/yamm3#d604f9ad80b46f361f38d06eb9157dbbbb91229a"
+  "packages": {
+    "": {
+      "name": "eclipsefdn-eclipse.org-common",
+      "version": "0.0.1",
+      "license": "EPL-2.0",
+      "dependencies": {
+        "eclipsefdn-solstice-assets": "0.0.130"
+      }
     },
-    "abbrev": {
+    "node_modules/@babel/code-frame": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+      "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+      "dependencies": {
+        "@babel/highlight": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.5.tgz",
+      "integrity": "sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg=="
+    },
+    "node_modules/@babel/core": {
+      "version": "7.12.3",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz",
+      "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==",
+      "dependencies": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/generator": "^7.12.1",
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helpers": "^7.12.1",
+        "@babel/parser": "^7.12.3",
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.12.1",
+        "@babel/types": "^7.12.1",
+        "convert-source-map": "^1.7.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.1",
+        "json5": "^2.1.2",
+        "lodash": "^4.17.19",
+        "resolve": "^1.3.2",
+        "semver": "^5.4.1",
+        "source-map": "^0.5.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz",
+      "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==",
+      "dependencies": {
+        "@babel/types": "^7.12.5",
+        "jsesc": "^2.5.1",
+        "source-map": "^0.5.0"
+      }
+    },
+    "node_modules/@babel/helper-annotate-as-pure": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
+      "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
+      "dependencies": {
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
+      "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
+      "dependencies": {
+        "@babel/helper-explode-assignable-expression": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz",
+      "integrity": "sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==",
+      "dependencies": {
+        "@babel/compat-data": "^7.12.5",
+        "@babel/helper-validator-option": "^7.12.1",
+        "browserslist": "^4.14.5",
+        "semver": "^5.5.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-create-class-features-plugin": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz",
+      "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==",
+      "dependencies": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-member-expression-to-functions": "^7.12.1",
+        "@babel/helper-optimise-call-expression": "^7.10.4",
+        "@babel/helper-replace-supers": "^7.12.1",
+        "@babel/helper-split-export-declaration": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-create-regexp-features-plugin": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz",
+      "integrity": "sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA==",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.10.4",
+        "@babel/helper-regex": "^7.10.4",
+        "regexpu-core": "^4.7.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-define-map": {
+      "version": "7.10.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
+      "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
+      "dependencies": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/types": "^7.10.5",
+        "lodash": "^4.17.19"
+      }
+    },
+    "node_modules/@babel/helper-explode-assignable-expression": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz",
+      "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==",
+      "dependencies": {
+        "@babel/types": "^7.12.1"
+      }
+    },
+    "node_modules/@babel/helper-function-name": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+      "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+      "dependencies": {
+        "@babel/helper-get-function-arity": "^7.10.4",
+        "@babel/template": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-get-function-arity": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+      "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+      "dependencies": {
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-hoist-variables": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
+      "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
+      "dependencies": {
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-member-expression-to-functions": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz",
+      "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==",
+      "dependencies": {
+        "@babel/types": "^7.12.1"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
+      "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
+      "dependencies": {
+        "@babel/types": "^7.12.5"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz",
+      "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.12.1",
+        "@babel/helper-replace-supers": "^7.12.1",
+        "@babel/helper-simple-access": "^7.12.1",
+        "@babel/helper-split-export-declaration": "^7.11.0",
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.12.1",
+        "@babel/types": "^7.12.1",
+        "lodash": "^4.17.19"
+      }
+    },
+    "node_modules/@babel/helper-optimise-call-expression": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+      "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+      "dependencies": {
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+      "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg=="
+    },
+    "node_modules/@babel/helper-regex": {
+      "version": "7.10.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz",
+      "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==",
+      "dependencies": {
+        "lodash": "^4.17.19"
+      }
+    },
+    "node_modules/@babel/helper-remap-async-to-generator": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz",
+      "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.10.4",
+        "@babel/helper-wrap-function": "^7.10.4",
+        "@babel/types": "^7.12.1"
+      }
+    },
+    "node_modules/@babel/helper-replace-supers": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz",
+      "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==",
+      "dependencies": {
+        "@babel/helper-member-expression-to-functions": "^7.12.1",
+        "@babel/helper-optimise-call-expression": "^7.10.4",
+        "@babel/traverse": "^7.12.5",
+        "@babel/types": "^7.12.5"
+      }
+    },
+    "node_modules/@babel/helper-simple-access": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz",
+      "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==",
+      "dependencies": {
+        "@babel/types": "^7.12.1"
+      }
+    },
+    "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
+      "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==",
+      "dependencies": {
+        "@babel/types": "^7.12.1"
+      }
+    },
+    "node_modules/@babel/helper-split-export-declaration": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+      "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+      "dependencies": {
+        "@babel/types": "^7.11.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+      "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz",
+      "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A=="
+    },
+    "node_modules/@babel/helper-wrap-function": {
+      "version": "7.12.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz",
+      "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==",
+      "dependencies": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz",
+      "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==",
+      "dependencies": {
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.12.5",
+        "@babel/types": "^7.12.5"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+      "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz",
+      "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-async-generator-functions": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz",
+      "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-remap-async-to-generator": "^7.12.1",
+        "@babel/plugin-syntax-async-generators": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-class-properties": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz",
+      "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==",
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-dynamic-import": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz",
+      "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-dynamic-import": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-export-namespace-from": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz",
+      "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-json-strings": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz",
+      "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-json-strings": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz",
+      "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz",
+      "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-numeric-separator": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz",
+      "integrity": "sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-object-rest-spread": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz",
+      "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+        "@babel/plugin-transform-parameters": "^7.12.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-optional-catch-binding": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz",
+      "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-optional-chaining": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz",
+      "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1",
+        "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-private-methods": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz",
+      "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==",
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz",
+      "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-async-generators": {
+      "version": "7.8.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-class-properties": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz",
+      "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-dynamic-import": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+      "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-export-namespace-from": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+      "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-json-strings": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-numeric-separator": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-chaining": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-top-level-await": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz",
+      "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-arrow-functions": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz",
+      "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-async-to-generator": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz",
+      "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-remap-async-to-generator": "^7.12.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-block-scoped-functions": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz",
+      "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-block-scoping": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz",
+      "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-classes": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz",
+      "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.10.4",
+        "@babel/helper-define-map": "^7.10.4",
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-optimise-call-expression": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-replace-supers": "^7.12.1",
+        "@babel/helper-split-export-declaration": "^7.10.4",
+        "globals": "^11.1.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-computed-properties": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz",
+      "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-destructuring": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz",
+      "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-dotall-regex": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz",
+      "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-duplicate-keys": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz",
+      "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-exponentiation-operator": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz",
+      "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==",
+      "dependencies": {
+        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-for-of": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz",
+      "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-function-name": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz",
+      "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==",
+      "dependencies": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-literals": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz",
+      "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-member-expression-literals": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz",
+      "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-amd": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz",
+      "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "babel-plugin-dynamic-import-node": "^2.3.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-commonjs": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz",
+      "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-simple-access": "^7.12.1",
+        "babel-plugin-dynamic-import-node": "^2.3.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-systemjs": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz",
+      "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==",
+      "dependencies": {
+        "@babel/helper-hoist-variables": "^7.10.4",
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "babel-plugin-dynamic-import-node": "^2.3.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-umd": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz",
+      "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz",
+      "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.12.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-new-target": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz",
+      "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-object-super": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz",
+      "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-replace-supers": "^7.12.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-parameters": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz",
+      "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-property-literals": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz",
+      "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-regenerator": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz",
+      "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==",
+      "dependencies": {
+        "regenerator-transform": "^0.14.2"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-reserved-words": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz",
+      "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-runtime": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz",
+      "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "resolve": "^1.8.1",
+        "semver": "^5.5.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-shorthand-properties": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz",
+      "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-spread": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz",
+      "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-sticky-regex": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz",
+      "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-regex": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-template-literals": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz",
+      "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-typeof-symbol": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz",
+      "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-escapes": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz",
+      "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-regex": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz",
+      "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/preset-env": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz",
+      "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==",
+      "dependencies": {
+        "@babel/compat-data": "^7.12.1",
+        "@babel/helper-compilation-targets": "^7.12.1",
+        "@babel/helper-module-imports": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-validator-option": "^7.12.1",
+        "@babel/plugin-proposal-async-generator-functions": "^7.12.1",
+        "@babel/plugin-proposal-class-properties": "^7.12.1",
+        "@babel/plugin-proposal-dynamic-import": "^7.12.1",
+        "@babel/plugin-proposal-export-namespace-from": "^7.12.1",
+        "@babel/plugin-proposal-json-strings": "^7.12.1",
+        "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1",
+        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
+        "@babel/plugin-proposal-numeric-separator": "^7.12.1",
+        "@babel/plugin-proposal-object-rest-spread": "^7.12.1",
+        "@babel/plugin-proposal-optional-catch-binding": "^7.12.1",
+        "@babel/plugin-proposal-optional-chaining": "^7.12.1",
+        "@babel/plugin-proposal-private-methods": "^7.12.1",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.12.1",
+        "@babel/plugin-syntax-async-generators": "^7.8.0",
+        "@babel/plugin-syntax-class-properties": "^7.12.1",
+        "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+        "@babel/plugin-syntax-json-strings": "^7.8.0",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
+        "@babel/plugin-syntax-optional-chaining": "^7.8.0",
+        "@babel/plugin-syntax-top-level-await": "^7.12.1",
+        "@babel/plugin-transform-arrow-functions": "^7.12.1",
+        "@babel/plugin-transform-async-to-generator": "^7.12.1",
+        "@babel/plugin-transform-block-scoped-functions": "^7.12.1",
+        "@babel/plugin-transform-block-scoping": "^7.12.1",
+        "@babel/plugin-transform-classes": "^7.12.1",
+        "@babel/plugin-transform-computed-properties": "^7.12.1",
+        "@babel/plugin-transform-destructuring": "^7.12.1",
+        "@babel/plugin-transform-dotall-regex": "^7.12.1",
+        "@babel/plugin-transform-duplicate-keys": "^7.12.1",
+        "@babel/plugin-transform-exponentiation-operator": "^7.12.1",
+        "@babel/plugin-transform-for-of": "^7.12.1",
+        "@babel/plugin-transform-function-name": "^7.12.1",
+        "@babel/plugin-transform-literals": "^7.12.1",
+        "@babel/plugin-transform-member-expression-literals": "^7.12.1",
+        "@babel/plugin-transform-modules-amd": "^7.12.1",
+        "@babel/plugin-transform-modules-commonjs": "^7.12.1",
+        "@babel/plugin-transform-modules-systemjs": "^7.12.1",
+        "@babel/plugin-transform-modules-umd": "^7.12.1",
+        "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1",
+        "@babel/plugin-transform-new-target": "^7.12.1",
+        "@babel/plugin-transform-object-super": "^7.12.1",
+        "@babel/plugin-transform-parameters": "^7.12.1",
+        "@babel/plugin-transform-property-literals": "^7.12.1",
+        "@babel/plugin-transform-regenerator": "^7.12.1",
+        "@babel/plugin-transform-reserved-words": "^7.12.1",
+        "@babel/plugin-transform-shorthand-properties": "^7.12.1",
+        "@babel/plugin-transform-spread": "^7.12.1",
+        "@babel/plugin-transform-sticky-regex": "^7.12.1",
+        "@babel/plugin-transform-template-literals": "^7.12.1",
+        "@babel/plugin-transform-typeof-symbol": "^7.12.1",
+        "@babel/plugin-transform-unicode-escapes": "^7.12.1",
+        "@babel/plugin-transform-unicode-regex": "^7.12.1",
+        "@babel/preset-modules": "^0.1.3",
+        "@babel/types": "^7.12.1",
+        "core-js-compat": "^3.6.2",
+        "semver": "^5.5.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/preset-modules": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
+      "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+        "@babel/plugin-transform-dotall-regex": "^7.4.4",
+        "@babel/types": "^7.4.4",
+        "esutils": "^2.0.2"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
+      "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
+      "dependencies": {
+        "regenerator-runtime": "^0.13.4"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+      "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+      "dependencies": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/parser": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz",
+      "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==",
+      "dependencies": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/generator": "^7.12.5",
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-split-export-declaration": "^7.11.0",
+        "@babel/parser": "^7.12.5",
+        "@babel/types": "^7.12.5",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0",
+        "lodash": "^4.17.19"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.12.6",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz",
+      "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "lodash": "^4.17.19",
+        "to-fast-properties": "^2.0.0"
+      }
+    },
+    "node_modules/@geedmo/yamm3": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/@geedmo/yamm3/-/yamm3-1.3.1.tgz",
+      "integrity": "sha512-WI2zymmEXud2q0a/7cdRWCr58gvZUcAHpbrSHA1rz1fU6n0mcAkmuKoTrRMF35mrWFxB/mliw4HEMRhoaIXmMA=="
+    },
+    "node_modules/@mrmlnc/readdir-enhanced": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+      "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+      "dependencies": {
+        "call-me-maybe": "^1.0.1",
+        "glob-to-regexp": "^0.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+      "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/@types/glob": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
+      "dependencies": {
+        "@types/minimatch": "*",
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
+      "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw=="
+    },
+    "node_modules/@types/minimatch": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+      "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
+    },
+    "node_modules/@types/node": {
+      "version": "14.14.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.8.tgz",
+      "integrity": "sha512-z/5Yd59dCKI5kbxauAJgw6dLPzW+TNOItNE00PkpzNwUIEwdj/Lsqwq94H5DdYBX7C13aRA0CY32BK76+neEUA=="
+    },
+    "node_modules/@types/q": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
+      "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
+    },
+    "node_modules/@vue/component-compiler-utils": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz",
+      "integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==",
+      "dependencies": {
+        "consolidate": "^0.15.1",
+        "hash-sum": "^1.0.2",
+        "lru-cache": "^4.1.2",
+        "merge-source-map": "^1.1.0",
+        "postcss": "^7.0.14",
+        "postcss-selector-parser": "^6.0.2",
+        "prettier": "^1.18.2",
+        "source-map": "~0.6.1",
+        "vue-template-es2015-compiler": "^1.9.0"
+      },
+      "optionalDependencies": {
+        "prettier": "^1.18.2"
+      }
+    },
+    "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dependencies": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "node_modules/@vue/component-compiler-utils/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@vue/component-compiler-utils/node_modules/yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+    },
+    "node_modules/@webassemblyjs/ast": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
+      "dependencies": {
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA=="
+    },
+    "node_modules/@webassemblyjs/helper-api-error": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw=="
+    },
+    "node_modules/@webassemblyjs/helper-buffer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA=="
+    },
+    "node_modules/@webassemblyjs/helper-code-frame": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
+      "dependencies": {
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-fsm": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw=="
+    },
+    "node_modules/@webassemblyjs/helper-module-context": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+      "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw=="
+    },
+    "node_modules/@webassemblyjs/helper-wasm-section": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+      "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/ieee754": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+      "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
+      "dependencies": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "node_modules/@webassemblyjs/leb128": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+      "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
+      "dependencies": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/utf8": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+      "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w=="
+    },
+    "node_modules/@webassemblyjs/wasm-edit": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+      "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/helper-wasm-section": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-opt": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-gen": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+      "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-opt": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+      "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+      "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+      "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-code-frame": "1.9.0",
+        "@webassemblyjs/helper-fsm": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-printer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+      "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+    },
+    "node_modules/@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+    },
+    "node_modules/accepts": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+      "dependencies": {
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "6.4.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+      "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "dependencies": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-errors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+      "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+      "peerDependencies": {
+        "ajv": ">=5.0.0"
+      }
+    },
+    "node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/alphanum-sort": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+      "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
+    },
+    "node_modules/ansi-colors": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+      "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ansi-html": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+      "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+      "engines": [
+        "node >= 0.8.0"
+      ],
+      "bin": {
+        "ansi-html": "bin/ansi-html"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+      "dependencies": {
+        "micromatch": "^3.1.4",
+        "normalize-path": "^2.1.1"
+      }
+    },
+    "node_modules/anymatch/node_modules/normalize-path": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+      "dependencies": {
+        "remove-trailing-separator": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+    },
+    "node_modules/are-we-there-yet": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+      "dependencies": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^2.0.6"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/arr-diff": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/array-flatten": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+      "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ=="
+    },
+    "node_modules/array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "dependencies": {
+        "array-uniq": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/array-unique": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/asn1.js": {
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+      "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+      "dependencies": {
+        "bn.js": "^4.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "node_modules/asn1.js/node_modules/bn.js": {
+      "version": "4.11.9",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+      "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+    },
+    "node_modules/assert": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+      "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+      "dependencies": {
+        "object-assign": "^4.1.1",
+        "util": "0.10.3"
+      }
+    },
+    "node_modules/assert/node_modules/inherits": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+      "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+    },
+    "node_modules/assert/node_modules/util": {
+      "version": "0.10.3",
+      "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+      "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+      "dependencies": {
+        "inherits": "2.0.1"
+      }
+    },
+    "node_modules/assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ast-types": {
+      "version": "0.9.6",
+      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
+      "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/async": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "dependencies": {
+        "lodash": "^4.17.14"
+      }
+    },
+    "node_modules/async-each": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
+    },
+    "node_modules/async-limiter": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+    },
+    "node_modules/atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "bin": {
+        "atob": "bin/atob.js"
+      },
+      "engines": {
+        "node": ">= 4.5.0"
+      }
+    },
+    "node_modules/autoprefixer": {
+      "version": "9.8.6",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
+      "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==",
+      "dependencies": {
+        "browserslist": "^4.12.0",
+        "caniuse-lite": "^1.0.30001109",
+        "colorette": "^1.2.1",
+        "normalize-range": "^0.1.2",
+        "num2fraction": "^1.2.2",
+        "postcss": "^7.0.32",
+        "postcss-value-parser": "^4.1.0"
+      },
+      "bin": {
+        "autoprefixer": "bin/autoprefixer"
+      },
+      "funding": {
+        "type": "tidelift",
+        "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+      }
+    },
+    "node_modules/babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "dependencies": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      }
+    },
+    "node_modules/babel-code-frame/node_modules/ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/babel-code-frame/node_modules/chalk": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+      "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+      "dependencies": {
+        "ansi-styles": "^2.2.1",
+        "escape-string-regexp": "^1.0.2",
+        "has-ansi": "^2.0.0",
+        "strip-ansi": "^3.0.0",
+        "supports-color": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/babel-code-frame/node_modules/js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+    },
+    "node_modules/babel-code-frame/node_modules/supports-color": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/babel-loader": {
+      "version": "8.2.1",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.1.tgz",
+      "integrity": "sha512-dMF8sb2KQ8kJl21GUjkW1HWmcsL39GOV5vnzjqrCzEPNY0S0UfMLnumidiwIajDSBmKhYf5iRW+HXaM4cvCKBw==",
+      "dependencies": {
+        "find-cache-dir": "^2.1.0",
+        "loader-utils": "^1.4.0",
+        "make-dir": "^2.1.0",
+        "pify": "^4.0.1",
+        "schema-utils": "^2.6.5"
+      },
+      "engines": {
+        "node": ">= 8.9"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0",
+        "webpack": ">=2"
+      }
+    },
+    "node_modules/babel-merge": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-2.0.1.tgz",
+      "integrity": "sha512-puTQQxuzS+0JlMyVdfsTVaCgzqjBXKPMv7oUANpYcHFY+7IptWZ4PZDYX+qBxrRMtrriuBA44LkKpS99EJzqVA==",
+      "dependencies": {
+        "@babel/core": "^7.0.0-beta.49",
+        "deepmerge": "^2.1.0",
+        "object.omit": "^3.0.0"
+      }
+    },
+    "node_modules/babel-plugin-dynamic-import-node": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+      "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+      "dependencies": {
+        "object.assign": "^4.1.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+    },
+    "node_modules/base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "dependencies": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/base/node_modules/define-property": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+      "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+      "dependencies": {
+        "is-descriptor": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/batch": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+      "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
+    },
+    "node_modules/big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+      "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "optional": true,
+      "dependencies": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
+    "node_modules/bl": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
+      "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
+      "dependencies": {
+        "readable-stream": "^2.3.5",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "node_modules/block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "dependencies": {
+        "inherits": "~2.0.0"
+      },
+      "engines": {
+        "node": "0.4 || >=0.5.8"
+      }
+    },
+    "node_modules/bluebird": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+    },
+    "node_modules/bn.js": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
+      "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ=="
+    },
+    "node_modules/body-parser": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+      "dependencies": {
+        "bytes": "3.1.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "on-finished": "~2.3.0",
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/body-parser/node_modules/bytes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/body-parser/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/body-parser/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "node_modules/bonjour": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+      "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+      "dependencies": {
+        "array-flatten": "^2.1.0",
+        "deep-equal": "^1.0.1",
+        "dns-equal": "^1.0.0",
+        "dns-txt": "^2.0.2",
+        "multicast-dns": "^6.0.1",
+        "multicast-dns-service-types": "^1.1.0"
+      }
+    },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+    },
+    "node_modules/bootstrap": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz",
+      "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+      "dependencies": {
+        "arr-flatten": "^1.1.0",
+        "array-unique": "^0.3.2",
+        "extend-shallow": "^2.0.1",
+        "fill-range": "^4.0.0",
+        "isobject": "^3.0.1",
+        "repeat-element": "^1.1.2",
+        "snapdragon": "^0.8.1",
+        "snapdragon-node": "^2.0.1",
+        "split-string": "^3.0.2",
+        "to-regex": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/brorand": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+    },
+    "node_modules/browserify-aes": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+      "dependencies": {
+        "buffer-xor": "^1.0.3",
+        "cipher-base": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.3",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/browserify-cipher": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+      "dependencies": {
+        "browserify-aes": "^1.0.4",
+        "browserify-des": "^1.0.0",
+        "evp_bytestokey": "^1.0.0"
+      }
+    },
+    "node_modules/browserify-des": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+      "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+      "dependencies": {
+        "cipher-base": "^1.0.1",
+        "des.js": "^1.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "node_modules/browserify-rsa": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+      "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+      "dependencies": {
+        "bn.js": "^5.0.0",
+        "randombytes": "^2.0.1"
+      }
+    },
+    "node_modules/browserify-sign": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+      "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+      "dependencies": {
+        "bn.js": "^5.1.1",
+        "browserify-rsa": "^4.0.1",
+        "create-hash": "^1.2.0",
+        "create-hmac": "^1.1.7",
+        "elliptic": "^6.5.3",
+        "inherits": "^2.0.4",
+        "parse-asn1": "^5.1.5",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      }
+    },
+    "node_modules/browserify-sign/node_modules/readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/browserify-sign/node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "dependencies": {
+        "pako": "~1.0.5"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.14.7",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.7.tgz",
+      "integrity": "sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==",
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001157",
+        "colorette": "^1.2.1",
+        "electron-to-chromium": "^1.3.591",
+        "escalade": "^3.1.1",
+        "node-releases": "^1.1.66"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/browserslist"
+      }
+    },
+    "node_modules/buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "node_modules/buffer-alloc": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "dependencies": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "node_modules/buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
+    },
+    "node_modules/buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
+    },
+    "node_modules/buffer-from": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+    },
+    "node_modules/buffer-indexof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+      "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
+    },
+    "node_modules/buffer-xor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+    },
+    "node_modules/builtin-status-codes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+    },
+    "node_modules/bytes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/cacache": {
+      "version": "13.0.1",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz",
+      "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==",
+      "dependencies": {
+        "chownr": "^1.1.2",
+        "figgy-pudding": "^3.5.1",
+        "fs-minipass": "^2.0.0",
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.2.2",
+        "infer-owner": "^1.0.4",
+        "lru-cache": "^5.1.1",
+        "minipass": "^3.0.0",
+        "minipass-collect": "^1.0.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.2",
+        "mkdirp": "^0.5.1",
+        "move-concurrently": "^1.0.1",
+        "p-map": "^3.0.0",
+        "promise-inflight": "^1.0.1",
+        "rimraf": "^2.7.1",
+        "ssri": "^7.0.0",
+        "unique-filename": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "dependencies": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz",
+      "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==",
+      "dependencies": {
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/call-me-maybe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
+      "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms="
+    },
+    "node_modules/caller-callsite": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+      "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+      "dependencies": {
+        "callsites": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/caller-path": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+      "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+      "dependencies": {
+        "caller-callsite": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+      "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/camel-case": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+      "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+      "dependencies": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.1.1"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-api": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+      "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+      "dependencies": {
+        "browserslist": "^4.0.0",
+        "caniuse-lite": "^1.0.0",
+        "lodash.memoize": "^4.1.2",
+        "lodash.uniq": "^4.5.0"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001159",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz",
+      "integrity": "sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA=="
+    },
+    "node_modules/caw": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
+      "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
+      "dependencies": {
+        "get-proxy": "^2.0.0",
+        "isurl": "^1.0.0-alpha5",
+        "tunnel-agent": "^0.6.0",
+        "url-to-options": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/charenc": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+      "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "2.1.8",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+      "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+      "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.",
+      "dependencies": {
+        "anymatch": "^2.0.0",
+        "async-each": "^1.0.1",
+        "braces": "^2.3.2",
+        "fsevents": "^1.2.7",
+        "glob-parent": "^3.1.0",
+        "inherits": "^2.0.3",
+        "is-binary-path": "^1.0.0",
+        "is-glob": "^4.0.0",
+        "normalize-path": "^3.0.0",
+        "path-is-absolute": "^1.0.0",
+        "readdirp": "^2.2.1",
+        "upath": "^1.1.1"
+      },
+      "optionalDependencies": {
+        "fsevents": "^1.2.7"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+    },
+    "node_modules/chrome-trace-event": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+      "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+      "dependencies": {
+        "tslib": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dependencies": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "dependencies": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/class-utils/node_modules/define-property": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+      "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+      "dependencies": {
+        "is-descriptor": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/class-utils/node_modules/is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "dependencies": {
+        "kind-of": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/class-utils/node_modules/is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dependencies": {
+        "kind-of": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/class-utils/node_modules/is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "dependencies": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/class-utils/node_modules/is-descriptor/node_modules/kind-of": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+      "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/classnames": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+      "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+    },
+    "node_modules/clean-css": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
+      "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+      "dependencies": {
+        "source-map": "~0.6.0"
+      },
+      "engines": {
+        "node": ">= 4.0"
+      }
+    },
+    "node_modules/clean-css/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/cliui/node_modules/ansi-regex": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/string-width": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/strip-ansi": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+      "dependencies": {
+        "ansi-regex": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/coa": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+      "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
+      "dependencies": {
+        "@types/q": "^1.5.1",
+        "chalk": "^2.4.1",
+        "q": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 4.0"
+      }
+    },
+    "node_modules/code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/collect.js": {
+      "version": "4.28.6",
+      "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.28.6.tgz",
+      "integrity": "sha512-NAyuk1DnCotRaDZIS5kJ4sptgkwOeYqElird10yziN5JBuwYOGkOTguhNcPn5g344IfylZecxNYZAVXgv19p5Q=="
+    },
+    "node_modules/collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "dependencies": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/color": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
+      "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
+      "dependencies": {
+        "color-convert": "^1.9.1",
+        "color-string": "^1.5.4"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+    },
+    "node_modules/color-string": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
+      "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
+      "dependencies": {
+        "color-name": "^1.0.0",
+        "simple-swizzle": "^0.2.2"
+      }
+    },
+    "node_modules/colorette": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
+      "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw=="
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+    },
+    "node_modules/commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+    },
+    "node_modules/component-emitter": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+    },
+    "node_modules/compressible": {
+      "version": "2.0.18",
+      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+      "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+      "dependencies": {
+        "mime-db": ">= 1.43.0 < 2"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/compression": {
+      "version": "1.7.4",
+      "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+      "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+      "dependencies": {
+        "accepts": "~1.3.5",
+        "bytes": "3.0.0",
+        "compressible": "~2.0.16",
+        "debug": "2.6.9",
+        "on-headers": "~1.0.2",
+        "safe-buffer": "5.1.2",
+        "vary": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/compression/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/compression/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "node_modules/concat": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz",
+      "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=",
+      "dependencies": {
+        "commander": "^2.9.0"
+      },
+      "bin": {
+        "concat": "bin/concat"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "node_modules/concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "engines": [
+        "node >= 0.8"
+      ],
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "node_modules/config-chain": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
+      "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
+      "dependencies": {
+        "ini": "^1.3.4",
+        "proto-list": "~1.2.1"
+      }
+    },
+    "node_modules/connect-history-api-fallback": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/console-browserify": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+      "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
+    },
+    "node_modules/console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+    },
+    "node_modules/consolidate": {
+      "version": "0.15.1",
+      "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
+      "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
+      "dependencies": {
+        "bluebird": "^3.1.1"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/constants-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+    },
+    "node_modules/content-disposition": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+      "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+      "dependencies": {
+        "safe-buffer": "5.1.2"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+      "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+      "dependencies": {
+        "safe-buffer": "~5.1.1"
+      }
+    },
+    "node_modules/cookie": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+      "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+    },
+    "node_modules/cookieconsent": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/cookieconsent/-/cookieconsent-3.1.1.tgz",
+      "integrity": "sha512-v8JWLJcI7Zs9NWrs8hiVldVtm3EBF70TJI231vxn6YToBGj0c9dvdnYwltydkAnrbBMOM/qX1xLFrnTfm5wTag=="
+    },
+    "node_modules/copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+      "dependencies": {
+        "aproba": "^1.1.1",
+        "fs-write-stream-atomic": "^1.0.8",
+        "iferr": "^0.1.5",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.0"
+      }
+    },
+    "node_modules/copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/core-js": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz",
+      "integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==",
+      "hasInstallScript": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-js-compat": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz",
+      "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==",
+      "dependencies": {
+        "browserslist": "^4.14.6",
+        "semver": "7.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-js-compat/node_modules/semver": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+      "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+    },
+    "node_modules/cosmiconfig": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+      "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+      "dependencies": {
+        "import-fresh": "^2.0.0",
+        "is-directory": "^0.3.1",
+        "js-yaml": "^3.13.1",
+        "parse-json": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/cosmiconfig/node_modules/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+      "dependencies": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/create-ecdh": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+      "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
+      "dependencies": {
+        "bn.js": "^4.1.0",
+        "elliptic": "^6.5.3"
+      }
+    },
+    "node_modules/create-ecdh/node_modules/bn.js": {
+      "version": "4.11.9",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+      "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+    },
+    "node_modules/create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "dependencies": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "node_modules/create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "dependencies": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dependencies": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      },
+      "engines": {
+        "node": ">=4.8"
+      }
+    },
+    "node_modules/crypt": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+      "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/crypto-browserify": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dependencies": {
+        "browserify-cipher": "^1.0.0",
+        "browserify-sign": "^4.0.0",
+        "create-ecdh": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "create-hmac": "^1.1.0",
+        "diffie-hellman": "^5.0.0",
+        "inherits": "^2.0.1",
+        "pbkdf2": "^3.0.3",
+        "public-encrypt": "^4.0.0",
+        "randombytes": "^2.0.0",
+        "randomfill": "^1.0.3"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/css-color-names": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+      "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/css-declaration-sorter": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
+      "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
+      "dependencies": {
+        "postcss": "^7.0.1",
+        "timsort": "^0.3.0"
+      },
+      "engines": {
+        "node": ">4"
+      }
+    },
+    "node_modules/css-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz",
+      "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==",
+      "dependencies": {
+        "babel-code-frame": "^6.26.0",
+        "css-selector-tokenizer": "^0.7.0",
+        "icss-utils": "^2.1.0",
+        "loader-utils": "^1.0.2",
+        "lodash": "^4.17.11",
+        "postcss": "^6.0.23",
+        "postcss-modules-extract-imports": "^1.2.0",
+        "postcss-modules-local-by-default": "^1.2.0",
+        "postcss-modules-scope": "^1.1.0",
+        "postcss-modules-values": "^1.3.0",
+        "postcss-value-parser": "^3.3.0",
+        "source-list-map": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 6.9.0 <7.0.0 || >= 8.9.0"
+      },
+      "peerDependencies": {
+        "webpack": "^4.0.0"
+      }
+    },
+    "node_modules/css-loader/node_modules/postcss": {
+      "version": "6.0.23",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+      "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+      "dependencies": {
+        "chalk": "^2.4.1",
+        "source-map": "^0.6.1",
+        "supports-color": "^5.4.0"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/css-loader/node_modules/postcss-value-parser": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+      "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
+    },
+    "node_modules/css-loader/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/css-select": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+      "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-what": "^3.2.1",
+        "domutils": "^1.7.0",
+        "nth-check": "^1.0.2"
+      }
+    },
+    "node_modules/css-select-base-adapter": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+      "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
+    },
+    "node_modules/css-selector-tokenizer": {
+      "version": "0.7.3",
+      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz",
+      "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "fastparse": "^1.1.2"
+      }
+    },
+    "node_modules/css-tree": {
+      "version": "1.0.0-alpha.37",
+      "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
+      "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==",
+      "dependencies": {
+        "mdn-data": "2.0.4",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/css-tree/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/css-what": {
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
+      "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
+      "engines": {
+        "node": ">= 6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cssesc": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+      "bin": {
+        "cssesc": "bin/cssesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/cssnano": {
+      "version": "4.1.10",
+      "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz",
+      "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==",
+      "dependencies": {
+        "cosmiconfig": "^5.0.0",
+        "cssnano-preset-default": "^4.0.7",
+        "is-resolvable": "^1.0.0",
+        "postcss": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/cssnano-preset-default": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz",
+      "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==",
+      "dependencies": {
+        "css-declaration-sorter": "^4.0.1",
+        "cssnano-util-raw-cache": "^4.0.1",
+        "postcss": "^7.0.0",
+        "postcss-calc": "^7.0.1",
+        "postcss-colormin": "^4.0.3",
+        "postcss-convert-values": "^4.0.1",
+        "postcss-discard-comments": "^4.0.2",
+        "postcss-discard-duplicates": "^4.0.2",
+        "postcss-discard-empty": "^4.0.1",
+        "postcss-discard-overridden": "^4.0.1",
+        "postcss-merge-longhand": "^4.0.11",
+        "postcss-merge-rules": "^4.0.3",
+        "postcss-minify-font-values": "^4.0.2",
+        "postcss-minify-gradients": "^4.0.2",
+        "postcss-minify-params": "^4.0.2",
+        "postcss-minify-selectors": "^4.0.2",
+        "postcss-normalize-charset": "^4.0.1",
+        "postcss-normalize-display-values": "^4.0.2",
+        "postcss-normalize-positions": "^4.0.2",
+        "postcss-normalize-repeat-style": "^4.0.2",
+        "postcss-normalize-string": "^4.0.2",
+        "postcss-normalize-timing-functions": "^4.0.2",
+        "postcss-normalize-unicode": "^4.0.1",
+        "postcss-normalize-url": "^4.0.1",
+        "postcss-normalize-whitespace": "^4.0.2",
+        "postcss-ordered-values": "^4.1.2",
+        "postcss-reduce-initial": "^4.0.3",
+        "postcss-reduce-transforms": "^4.0.2",
+        "postcss-svgo": "^4.0.2",
+        "postcss-unique-selectors": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/cssnano-util-get-arguments": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz",
+      "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/cssnano-util-get-match": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz",
+      "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/cssnano-util-raw-cache": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
+      "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
+      "dependencies": {
+        "postcss": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/cssnano-util-same-parent": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
+      "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/csso": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/csso/-/csso-4.1.1.tgz",
+      "integrity": "sha512-Rvq+e1e0TFB8E8X+8MQjHSY6vtol45s5gxtLI/018UsAn2IBMmwNEZRM/h+HVnAJRHjasLIKKUO3uvoMM28LvA==",
+      "dependencies": {
+        "css-tree": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/csso/node_modules/css-tree": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.1.tgz",
+      "integrity": "sha512-NVN42M2fjszcUNpDbdkvutgQSlFYsr1z7kqeuCagHnNLBfYor6uP1WL1KrkmdYZ5Y1vTBCIOI/C/+8T98fJ71w==",
+      "dependencies": {
+        "mdn-data": "2.0.14",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/csso/node_modules/mdn-data": {
+      "version": "2.0.14",
+      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+      "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
+    },
+    "node_modules/csso/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/cyclist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+      "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
+    },
+    "node_modules/debug": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+      "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decode-uri-component": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/decompress": {
+      "version": "4