From 070ad74a7cbe5fc7c4769b7f28904fa7449571bb Mon Sep 17 00:00:00 2001
From: Harald Ponce de Leon <hpdl@oscommerce.com>
Date: Wed, 23 Nov 2016 01:58:36 +0100
Subject: [PATCH 1/3] throw a custom exception when a connection to the
 database fails; add $options parameter to disable error logging

---
 catalog/includes/OSC/OM/Db.php             | 29 +++++++++++++++++++---
 catalog/includes/OSC/OM/Db/MySQL.php       |  3 ++-
 catalog/includes/OSC/Sites/Admin/Admin.php |  9 +++++--
 catalog/includes/OSC/Sites/Shop/Shop.php   |  9 +++++--
 catalog/install/rpc.php                    |  4 +--
 5 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/catalog/includes/OSC/OM/Db.php b/catalog/includes/OSC/OM/Db.php
index cdb82f106..f75bee84c 100644
--- a/catalog/includes/OSC/OM/Db.php
+++ b/catalog/includes/OSC/OM/Db.php
@@ -21,6 +21,7 @@ class Db extends \PDO
     protected $table_prefix;
     protected $port;
     protected $driver_options = [];
+    protected $options = [];
 
     public static function initialize(
         $server = null,
@@ -28,7 +29,8 @@ public static function initialize(
         $password = null,
         $database = null,
         $port = null,
-        array $driver_options = []
+        array $driver_options = null,
+        array $options = null
     ) {
         if (!isset($server)) {
             $server = OSCOM::getConfig('db_server');
@@ -46,6 +48,10 @@ public static function initialize(
             $database = OSCOM::getConfig('db_database');
         }
 
+        if (!is_array($driver_options)) {
+            $driver_options = [];
+        }
+
         if (!isset($driver_options[\PDO::ATTR_ERRMODE])) {
             $driver_options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;
         }
@@ -58,8 +64,25 @@ public static function initialize(
             $driver_options[\PDO::ATTR_STATEMENT_CLASS] = array('OSC\OM\DbStatement');
         }
 
-        $class = 'OSC\OM\Db\MySQL';
-        $object = new $class($server, $username, $password, $database, $port, $driver_options);
+        if (!is_array($options)) {
+            $options = [];
+        }
+
+        $object = false;
+
+        try {
+            $class = 'OSC\OM\Db\MySQL';
+            $object = new $class($server, $username, $password, $database, $port, $driver_options, $options);
+        } catch (\Exception $e) {
+            $message = $e->getMessage();
+            // $message .= "\n" . $e->getTraceAsString(); // the trace will contain the password in plain text
+
+            if (!isset($options['log_errors']) || ($options['log_errors'] === true)) {
+                error_log('OSC\OM\Db::initialize(): ' . $message);
+            }
+
+            throw new \Exception($message, $e->getCode());
+        }
 
         return $object;
     }
diff --git a/catalog/includes/OSC/OM/Db/MySQL.php b/catalog/includes/OSC/OM/Db/MySQL.php
index 341dc8d1a..1d84bf392 100644
--- a/catalog/includes/OSC/OM/Db/MySQL.php
+++ b/catalog/includes/OSC/OM/Db/MySQL.php
@@ -10,7 +10,7 @@
 
 class MySQL extends \OSC\OM\Db
 {
-    public function __construct($server, $username, $password, $database, $port, $driver_options)
+    public function __construct($server, $username, $password, $database, $port, $driver_options, $options)
     {
         $this->server = $server;
         $this->username = $username;
@@ -18,6 +18,7 @@ public function __construct($server, $username, $password, $database, $port, $dr
         $this->database = $database;
         $this->port = $port;
         $this->driver_options = $driver_options;
+        $this->options = $options;
 
         if (!isset($this->driver_options[\PDO::MYSQL_ATTR_INIT_COMMAND])) {
             // STRICT_ALL_TABLES 5.0.2
diff --git a/catalog/includes/OSC/Sites/Admin/Admin.php b/catalog/includes/OSC/Sites/Admin/Admin.php
index ff9175bbf..bf4a22e1a 100644
--- a/catalog/includes/OSC/Sites/Admin/Admin.php
+++ b/catalog/includes/OSC/Sites/Admin/Admin.php
@@ -29,8 +29,13 @@ protected function init()
         $OSCOM_Cookies = new Cookies();
         Registry::set('Cookies', $OSCOM_Cookies);
 
-        $OSCOM_Db = Db::initialize();
-        Registry::set('Db', $OSCOM_Db);
+        try {
+            $OSCOM_Db = Db::initialize();
+            Registry::set('Db', $OSCOM_Db);
+        } catch (\Exception $e) {
+            include(OSCOM::getConfig('dir_root', 'Shop') . 'includes/error_documents/maintenance.php');
+            exit;
+        }
 
         Registry::set('Hooks', new Hooks());
 
diff --git a/catalog/includes/OSC/Sites/Shop/Shop.php b/catalog/includes/OSC/Sites/Shop/Shop.php
index 656922e77..f92bff8bf 100644
--- a/catalog/includes/OSC/Sites/Shop/Shop.php
+++ b/catalog/includes/OSC/Sites/Shop/Shop.php
@@ -27,8 +27,13 @@ protected function init()
         $OSCOM_Cookies = new Cookies();
         Registry::set('Cookies', $OSCOM_Cookies);
 
-        $OSCOM_Db = Db::initialize();
-        Registry::set('Db', $OSCOM_Db);
+        try {
+            $OSCOM_Db = Db::initialize();
+            Registry::set('Db', $OSCOM_Db);
+        } catch (\Exception $e) {
+            include(OSCOM::getConfig('dir_root') . 'includes/error_documents/maintenance.php');
+            exit;
+        }
 
         Registry::set('Hooks', new Hooks());
 
diff --git a/catalog/install/rpc.php b/catalog/install/rpc.php
index 62c1a6011..b0d603f3e 100644
--- a/catalog/install/rpc.php
+++ b/catalog/install/rpc.php
@@ -61,7 +61,7 @@
 
       case 'dbCheck':
         try {
-          $OSCOM_Db = Db::initialize(isset($_POST['server']) ? $_POST['server'] : '', isset($_POST['username']) ? $_POST['username'] : '', isset($_POST['password']) ? $_POST['password'] : '', isset($_POST['name']) ? $_POST['name'] : '');
+          $OSCOM_Db = Db::initialize(isset($_POST['server']) ? $_POST['server'] : '', isset($_POST['username']) ? $_POST['username'] : '', isset($_POST['password']) ? $_POST['password'] : '', isset($_POST['name']) ? $_POST['name'] : '', null, null, ['log_errors' => false]);
 
           $result['status'] = '1';
           $result['message'] = 'success';
@@ -71,7 +71,7 @@
 
           if (($e->getCode() == '1049') && isset($_GET['createDb']) && ($_GET['createDb'] == 'true')) {
             try {
-              $OSCOM_Db = Db::initialize($_POST['server'], $_POST['username'], $_POST['password'], '');
+              $OSCOM_Db = Db::initialize($_POST['server'], $_POST['username'], $_POST['password'], '', null, null, ['log_errors' => false]);
 
               $OSCOM_Db->exec('create database ' . Db::prepareIdentifier($_POST['name']) . ' character set utf8 collate utf8_unicode_ci');
 

From aaed00df3aaed67b38005d9dfb38a557a974fa12 Mon Sep 17 00:00:00 2001
From: Harald Ponce de Leon <hpdl@oscommerce.com>
Date: Wed, 23 Nov 2016 01:59:51 +0100
Subject: [PATCH 2/3] check if Session is registered first; check if
 SEARCH_ENGINE_FRIENDLY_URLS is defined

---
 catalog/includes/OSC/OM/OSCOM.php | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/catalog/includes/OSC/OM/OSCOM.php b/catalog/includes/OSC/OM/OSCOM.php
index b7e12b24f..126a6123b 100644
--- a/catalog/includes/OSC/OM/OSCOM.php
+++ b/catalog/includes/OSC/OM/OSCOM.php
@@ -121,8 +121,6 @@ public static function isRPC()
 
     public static function link($page, $parameters = null, $add_session_id = true, $search_engine_safe = true)
     {
-        $OSCOM_Session = Registry::get('Session');
-
         $page = HTML::sanitize($page);
 
         $site = $req_site = static::$site;
@@ -170,9 +168,13 @@ public static function link($page, $parameters = null, $add_session_id = true, $
         }
 
 // Add the session ID when moving from different HTTP and HTTPS servers, or when SID is defined
-        if (($add_session_id == true) && $OSCOM_Session->hasStarted() && ($OSCOM_Session->isForceCookies() === false)) {
-            if ((strlen(SID) > 0) || (((HTTP::getRequestType() == 'NONSSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'https')) || ((HTTP::getRequestType() == 'SSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'http')))) {
-                $link .= $separator . HTML::sanitize(session_name() . '=' . session_id());
+        if (($add_session_id == true) && Registry::exists('Session')) {
+            $OSCOM_Session = Registry::get('Session');
+
+            if ($OSCOM_Session->hasStarted() && ($OSCOM_Session->isForceCookies() === false)) {
+                if ((strlen(SID) > 0) || (((HTTP::getRequestType() == 'NONSSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'https')) || ((HTTP::getRequestType() == 'SSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'http')))) {
+                    $link .= $separator . HTML::sanitize(session_name() . '=' . session_id());
+                }
             }
         }
 
@@ -180,7 +182,7 @@ public static function link($page, $parameters = null, $add_session_id = true, $
             $link = str_replace('&&', '&', $link);
         }
 
-        if ((SEARCH_ENGINE_FRIENDLY_URLS == 'true') && ($search_engine_safe == true)) {
+        if (($search_engine_safe == true) && defined('SEARCH_ENGINE_FRIENDLY_URLS') && (SEARCH_ENGINE_FRIENDLY_URLS == 'true')) {
             $link = str_replace(['?', '&', '='], '/', $link);
         }
 

From 76e25afd467569944e0689349047e357dd538e64 Mon Sep 17 00:00:00 2001
From: Harald Ponce de Leon <hpdl@oscommerce.com>
Date: Wed, 23 Nov 2016 02:00:31 +0100
Subject: [PATCH 3/3] new maintenance page; update 404 page

---
 catalog/includes/error_documents/404.php      | 24 ++++++++++--
 .../includes/error_documents/maintenance.php  | 38 +++++++++++++++++++
 2 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 catalog/includes/error_documents/maintenance.php

diff --git a/catalog/includes/error_documents/404.php b/catalog/includes/error_documents/404.php
index c5de72da4..6f00aff1d 100644
--- a/catalog/includes/error_documents/404.php
+++ b/catalog/includes/error_documents/404.php
@@ -12,8 +12,26 @@
 http_response_code(404);
 ?>
 
-<h1>Error - Page Not Found (404)</h1>
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+<title>Error - Page Not Found</title>
+<link href="<?= OSCOM::link('Shop/ext/bootstrap/css/bootstrap.min.css', null, false); ?>" rel="stylesheet">
+<link href="<?= OSCOM::link('Shop/ext/font-awesome/4.7.0/css/font-awesome.min.css', null, false); ?>" rel="stylesheet">
+<script src="<?= OSCOM::link('Shop/ext/jquery/jquery-3.1.1.min.js', null, false); ?>"></script>
+</head>
+<body>
+<div class="container">
+  <div class="jumbotron" style="margin-top: 40px;">
+    <h1>This Page is Missing</h1>
 
-<div>
-  <?php echo HTML::button('Continue', 'glyphicon glyphicon-chevron-right', OSCOM::link('index.php')); ?>
+    <p>It looks like this page is missing. Please continue back to our website and try again.</p>
+
+    <p style="margin-top: 40px;"><?= HTML::button('Return to website', 'fa fa-chevron-right', OSCOM::link('index.php'), null, 'btn-primary'); ?></p>
+  </div>
 </div>
+<script src="<?= OSCOM::link('Shop/ext/bootstrap/js/bootstrap.min.js', null, false); ?>"></script>
+</body>
+</html>
diff --git a/catalog/includes/error_documents/maintenance.php b/catalog/includes/error_documents/maintenance.php
new file mode 100644
index 000000000..cc157369c
--- /dev/null
+++ b/catalog/includes/error_documents/maintenance.php
@@ -0,0 +1,38 @@
+<?php
+/**
+  * osCommerce Online Merchant
+  *
+  * @copyright (c) 2016 osCommerce; https://www.oscommerce.com
+  * @license MIT; https://www.oscommerce.com/license/mit.txt
+  */
+
+use OSC\OM\HTML;
+use OSC\OM\OSCOM;
+
+http_response_code(503);
+header('Retry-After: 300');
+?>
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+<title>Maintenance</title>
+<link href="<?= OSCOM::link('Shop/ext/bootstrap/css/bootstrap.min.css', null, false); ?>" rel="stylesheet">
+<link href="<?= OSCOM::link('Shop/ext/font-awesome/4.7.0/css/font-awesome.min.css', null, false); ?>" rel="stylesheet">
+<script src="<?= OSCOM::link('Shop/ext/jquery/jquery-3.1.1.min.js', null, false); ?>"></script>
+</head>
+<body>
+<div class="container">
+  <div class="jumbotron" style="margin-top: 40px;">
+    <h1>We'll be back soon!</h1>
+
+    <p>We're currently working on and improving our website. We'll be back in a few moments..</p>
+
+    <p style="margin-top: 40px;"><?= HTML::button('Return to website', 'fa fa-refresh', OSCOM::link('index.php'), null, 'btn-primary'); ?></p>
+  </div>
+</div>
+<script src="<?= OSCOM::link('Shop/ext/bootstrap/js/bootstrap.min.js', null, false); ?>"></script>
+</body>
+</html>