Jump to content

ERRNO: 2 TEXT: htmlspecialchars()


ohno

Recommended Posts

Not sure how to debug this. I have the following error that is ONLY happening when our site has a PCI scan running : -

ERRNO: 2
TEXT: htmlspecialchars() expects parameter 1 to be string, array given
LOCATION: /home/bttorj45/public_html/smarty_templates_c/dbbe565f1731d4158472b66b75c85442498e81b9_0.file.top_menu_bar.tpl.php, line 42, at April 11, 2020, 5:05 pm
Showing backtrace:
htmlspecialchars(Array[1], "3", "UTF-8", true) # line 42, file: /home/siteaddress/public_html/smarty_templates_c/dbbe565f1731d4158472b66b75c85442498e81b9_0.file.top_menu_bar.tpl.php
content_5e83087341d089_14126332(Object:Smarty_Internal_Template) # line 123, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_resource_base.php
Smarty_Template_Resource_Base.getRenderedTemplateCode(Object:Smarty_Internal_Template) # line 114, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_compiled.php
Smarty_Template_Compiled.render(Object:Smarty_Internal_Template) # line 216, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_template.php
Smarty_Internal_Template.render() # line 385, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_template.php
Smarty_Internal_Template._subTemplateRender("file:page_elements/top_menu_bar.tpl", null, null, "0", "120", Array[0], "0", false) # line 56, file: /home/siteaddress/public_html/smarty_templates_c/0e4c1495f7a25cef1d85553f951690964f702a5a_0.file.error404.tpl.php
content_5e4ffba4a49c66_36622821(Object:Smarty_Internal_Template) # line 123, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_resource_base.php
Smarty_Template_Resource_Base.getRenderedTemplateCode(Object:Smarty_Internal_Template) # line 114, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_compiled.php
Smarty_Template_Compiled.render(Object:Smarty_Internal_Template) # line 216, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_template.php
Smarty_Internal_Template.render(false, "1") # line 232, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_templatebase.php
Smarty_Internal_TemplateBase._execute(Object:Smarty_Internal_Template, null, null, null, "1") # line 134, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_templatebase.php
Smarty_Internal_TemplateBase.display("pages/error404.tpl") # line 65, file: /home/siteaddress/public_html/errors/404.php
include("/home/siteaddress/public_html/errors/404.php") # line 34, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php
Product.init("api") # line 5, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php
smarty_function_load_product(Array[2], Object:Smarty_Internal_Template) # line 39, file: /home/siteaddress/public_html/smarty_templates_c/53725e8a2fc4b6c7c0c42e801dab2741a0994a8e_0.file.product.tpl.php
content_5e579e9761f086_59385269(Object:Smarty_Internal_Template) # line 123, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_resource_base.php
Smarty_Template_Resource_Base.getRenderedTemplateCode(Object:Smarty_Internal_Template) # line 114, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_template_compiled.php
Smarty_Template_Compiled.render(Object:Smarty_Internal_Template) # line 216, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_template.php
Smarty_Internal_Template.render(false, "1") # line 232, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_templatebase.php
Smarty_Internal_TemplateBase._execute(Object:Smarty_Internal_Template, null, null, null, "1") # line 134, file: /home/siteaddress/public_html/include/smarty/sysplugins/smarty_internal_templatebase.php
Smarty_Internal_TemplateBase.display("pages/product.tpl") # line 85, file: /home/siteaddress/public_html/dirs.php

I ***think*** the scan must be inputting something in the search box to cause this (I'm awaiting info from Security Metrics with regard to this).

{load_chat assign="chat"}

{if $chat->mChat}
<script type="text/javascript" id="763333b0f312f025d780a8f4451bf6f3" src="https://www.siteaddress.com/online-support/script.php?id=763333b0f312f025d780a8f4451bf6f3"></script>
{/if}
{if !$chat->mChat && $settings->mSettings[13]}
<script type="text/javascript" id="aaa07817d7cd2a7dce9e0ffac6286dbb" src="https://www.siteaddress.com/online-support/script.php?id=aaa07817d7cd2a7dce9e0ffac6286dbb"></script>
{/if}

<div id="menu_switch"><i class="fa fa-bars fa toggler"></i></div>
<form id="product_search" method="get" action="{$smarty.const.SITE_ROOT}/searchresults/">
    <input type="text" name="search" placeholder="&#xf002; Product Search" style="font-family: FontAwesome, Arial; font-style: normal; font-size:18px;" {if isset($smarty.request.search) && $settings->mSettings[107]}value="{$smarty.request.search|escape:'htmlall'}"{/if} /><button type="submit" class="button"><i class="fa fa-search" aria-hidden="true"></i> <i class="fa fa-caret-right" aria-hidden="true"></i></button>
</form>
<form id="code_search" method="post" action="{$smarty.const.SITE_ROOT}/cart/quickadd.php">
    <input type="text" name="code" maxlength="14" placeholder="&#xf061; Product Code" style="font-family: FontAwesome, Arial; font-style: normal; font-size:18px;" /><button type="submit" name="submit" class="orange"><i class="fa fa-shopping-cart" aria-hidden="true"></i> Quick Add <i class="fa fa-caret-right" aria-hidden="true"></i></button>
</form>
{if !isset($hidecart) && isset($cartsmall) && $cartsmall->mCart.sub > 0}
    <p id="view_cart"><a class="button orange" href="{$smarty.const.SITE_ROOT}/cart/"><span class="hidden-xs hidden-sm"><i class="fa fa-shopping-cart" aria-hidden="true"></i> View Cart &nbsp;</span>&pound;{$cartsmall->mCart.sub} <i class="fa fa-caret-right" aria-hidden="true"></i></a></p>
{/if}
<script>
$('.toggler').click(function() {
$(this).toggleClass("fa-bars fa-times");
});
</script>

 

function.load_search.php :-

 

<?php
      
   function smarty_function_load_search($params, $smarty) {
      $search = new Search();
      $search->init();
      $smarty->assign($params['assign'], $search);
   }
   
   class Search {
      
      // public fields
      public $mSearchString;
        public $mSearchArray;
        public $mProducts;
        public $mProductCount;
      
      // private fields
        private $mDoSettings;
      private $mDoCatalogue;
      
      function __construct() {
            require_once FILE_ROOT . '/data_objects/do_settings.php';
            $this->mDoSettings = new DoSettings();
         require_once FILE_ROOT . '/data_objects/do_catalogue.php';
         $this->mDoCatalogue = new DoCatalogue();
           
            if (isset($_REQUEST['search']) && strlen(trim($_REQUEST['search']))>0 ) {
                $this->mSearchString = trim(stripslashes($_REQUEST['search']));
                $this->mSearchArray = explode(" ", $this->mSearchString);
            
            } else {
                header ("Location: /emptysearch/");
            die ();
            }
      }
      
      public function init() {
            $this->mProducts = $this->mDoCatalogue->SearchProducts($this->mSearchArray);
            $this->mProductCount = count($this->mProducts);
            for ($i = 0; $i < count($this->mProducts); $i++) {
                $this->mProducts[$i]['price_inc'] = number_format($this->mProducts[$i]['price'] * (($this->mDoSettings->GetSetting(1) / 100) + 1), 2, ".", ",");
            }
      }
      
   }
   
?>

 

do_catalogue.php :-

 

public function SearchProducts($search) {
         $fields = array("code", "title", "keywords");
            $query_string = "SELECT p.code, p.title, p.cattext, p.price, p.img, p.url, p.available, p.due, p.special, p.newproduct, p.discontinued, c.name, c.menulinktext FROM " . $this->mProductTable . " p " .
                "JOIN categories c ON p.category = c.id " .
                "WHERE ((";
            for ($f = 0; $f < count($fields); $f++) {
                if ($f != 0) { $query_string .= ") OR ("; }
                for ($s = 0; $s < count($search); $s++) {
                    if ($s != 0) { $query_string .= " AND "; }
                    $query_string .= "p." . $fields[$f] . " LIKE '%" . $this->mDoQuery->dbManager->DbEscape($search[$s]) . "%'";
                }
            }
         $query_string .= ")) AND active=1 AND live=1 " .
                "ORDER BY p.rating ASC";
            return $this->mDoQuery->dbManager->DbGetAll($query_string);
        }

 

Any idea's how to fix it? I can't replicate it with a specific issue as I don't know what the scan is doing to cause this! Thanks

Link to comment
Share on other sites

If you skip over the template stuff in the backtrace, you'll see these two lines:

include("/home/siteaddress/public_html/errors/404.php") # line 34, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php
Product.init("api") # line 5, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php

What is the code for function.load_product.php?

Link to comment
Share on other sites

2 minutes ago, requinix said:

If you skip over the template stuff in the backtrace, you'll see these two lines:


include("/home/siteaddress/public_html/errors/404.php") # line 34, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php
Product.init("api") # line 5, file: /home/siteaddress/public_html/smarty_plugins/function.load_product.php

What is the code for function.load_product.php?

<?php
		
	function smarty_function_load_product($params, $smarty) {
		$product = new Product();
		$product->init($params['dir']);
		$smarty->assign($params['assign'], $product);
	}
	
	class Product {
		
		// public fields
		public $mProduct;
        //public $mImages;
        //public $mImageCount;
        public $mOptions;
        public $mXsells;
		
		// private fields
        private $mDoSettings;
		private $mDoCatalogue;
		
		function __construct() {
            require_once FILE_ROOT . '/data_objects/do_settings.php';
            $this->mDoSettings = new DoSettings();
			require_once FILE_ROOT . '/data_objects/do_catalogue.php';
			$this->mDoCatalogue = new DoCatalogue();
		}
		
		public function init($dir) {
            $this->mProduct = $this->mDoCatalogue->GetProductFromDir(trim(stripslashes($dir)));
            if (!$this->mProduct) {
                header('HTTP/1.1 404 Not Found');
                $_GET['e'] = 404;
                include(FILE_ROOT . '/errors/404.php');
                exit();
            }
            $this->mProduct['price_inc'] = number_format($this->mProduct['price'] * (($this->mDoSettings->GetSetting(1) / 100) + 1), 2, ".", ",");
            
            $options = trim($this->mProduct['optionprods'], ",\t\n\r\0\x0B");
            $options_ids = explode(",", $options);
            for ($i = 0; $i < count($options_ids); $i++) {
                if (is_numeric($options_ids[$i])) {
                    $product = $this->mDoCatalogue->GetProduct((int)$options_ids[$i]);
                    if ($product) {
                        $product['price_inc'] = number_format($product['price'] * (($this->mDoSettings->GetSetting(1) / 100) + 1), 2, ".", ",");
                        $this->mOptions[] = $product;
                    }
                    
                }
            }
            $this->mXsells = $this->mDoCatalogue->GetXsells($this->mProduct['productid']);
            shuffle($this->mXsells);
		}
		
	}
	
?>

 

Link to comment
Share on other sites

function.load_product.php IS the above code. The tpl was already posted, it's this code : -

 

{load_chat assign="chat"}

{if $chat->mChat}
<script type="text/javascript" id="763333b0f312f025d780a8f4451bf6f3" src="https://www.siteaddress.com/online-support/script.php?id=763333b0f312f025d780a8f4451bf6f3"></script>
{/if}
{if !$chat->mChat && $settings->mSettings[13]}
<script type="text/javascript" id="aaa07817d7cd2a7dce9e0ffac6286dbb" src="https://www.siteaddress.com/online-support/script.php?id=aaa07817d7cd2a7dce9e0ffac6286dbb"></script>
{/if}

<div id="menu_switch"><i class="fa fa-bars fa toggler"></i></div>
<form id="product_search" method="get" action="{$smarty.const.SITE_ROOT}/searchresults/">
    <input type="text" name="search" placeholder="&#xf002; Product Search" style="font-family: FontAwesome, Arial; font-style: normal; font-size:18px;" {if isset($smarty.request.search) && $settings->mSettings[107]}value="{$smarty.request.search|escape:'htmlall'}"{/if} /><button type="submit" class="button"><i class="fa fa-search" aria-hidden="true"></i> <i class="fa fa-caret-right" aria-hidden="true"></i></button>
</form>
<form id="code_search" method="post" action="{$smarty.const.SITE_ROOT}/cart/quickadd.php">
    <input type="text" name="code" maxlength="14" placeholder="&#xf061; Product Code" style="font-family: FontAwesome, Arial; font-style: normal; font-size:18px;" /><button type="submit" name="submit" class="orange"><i class="fa fa-shopping-cart" aria-hidden="true"></i> Quick Add <i class="fa fa-caret-right" aria-hidden="true"></i></button>
</form>
{if !isset($hidecart) && isset($cartsmall) && $cartsmall->mCart.sub > 0}
    <p id="view_cart"><a class="button orange" href="{$smarty.const.SITE_ROOT}/cart/"><span class="hidden-xs hidden-sm"><i class="fa fa-shopping-cart" aria-hidden="true"></i> View Cart &nbsp;</span>&pound;{$cartsmall->mCart.sub} <i class="fa fa-caret-right" aria-hidden="true"></i></a></p>
{/if}
<script>

 Hopefully that helps?

Link to comment
Share on other sites

Oh, that's what the file was?

I think the issue is in

{$smarty.request.search|escape:'htmlall'}

That's the only place that uses unknown input. The search was an array, as in search[]=....

Submit a regular search, then go into your browser's address bar and add brackets to the search=. Then see what happens.

How to fix that, it's kinda up to you. Standard MVC is that you should be passing the search value into the view, not getting it from the request. If you did that then you would validate the search value in your regular code: the 404 page, and any other place that ends up including top_menu_bar.

 

33 minutes ago, ohno said:

function.load_product.php IS the above code.

Right, yes, you did post the code I asked about. What I meant was "well that's not where the problem is". Was rather ambiguous, now that I look at it again.

Link to comment
Share on other sites

That gives a slightly different error in the log : -

 

ERRNO: 2 
TEXT: trim() expects parameter 1 to be string, array given 
LOCATION: /home/website/public_html/smarty_plugins/function.load_search.php, line 27, at April 20, 2020, 7:00 pm

 

function.load_search.php is above too.

Now, I have no clue how to fix it! Any idea's what code I'd need to fix it?

 

Edited by ohno
Link to comment
Share on other sites

38 minutes ago, ohno said:

That gives a slightly different error in the log : -

new error.

38 minutes ago, ohno said:

Now, I have no clue how to fix it! Any idea's what code I'd need to fix it?

You have to fix your code so that it doesn't assume everything, like query string parameters, are in the format you expect. This particular problem you're dealing with is something most PHP developers never even care about. They should, they just don't.

2 minutes ago, ohno said:

Could I simply do : -

 


$this->mSearchString = str_replace ( "[", " ",($_REQUEST['search']));

To prevent an array in the search?

No. Not only will the code not make the problem go away (and actually create a new problem along the way), what you're trying to do is not a good idea.

It'll take me longer to explain what I'm thinking in words than in code, so here:

class SearchQuery {

	public $value = "";

	public static function readFromRequest() {
		$query = new self();
		if (isset($_GET["search"]) && is_string($_GET["search"])) {
			$query->value = $_GET["search"];
		}
		return $query;
	}

}

$query = SearchQuery::readFromRequest();
// pass $query around to places that need to know about searching

 

Link to comment
Share on other sites

This is what he did.....

new function.load_search_query.php file

<?php
		
	function smarty_function_load_search_query($params, $smarty) {
		$query = new SearchQuery();
    $smarty->assign('query', $query->readFromRequest());
	}
	
	class SearchQuery {

    public $value = "";
  
    public static function readFromRequest() {
      $query = new self();
      if (isset($_GET["search"]) && is_string($_GET["search"])) {
        $query->value = $_GET["search"];
      }
      return $query;
    }
  
  }
	
?>

 

Modified function.load_search.php : -

 

function __construct() {
            require_once FILE_ROOT . '/data_objects/do_settings.php';
            $this->mDoSettings = new DoSettings();
			require_once FILE_ROOT . '/data_objects/do_catalogue.php';
			$this->mDoCatalogue = new DoCatalogue();
            
        
				if (!isset($_REQUEST['search']) || !is_string($_REQUEST['search']) ) {
					header ("Location: /emptysearch/");
					die ();
				}
				
				
				if (strlen(trim($_REQUEST['search']))>0 ) {
					$this->mSearchString = trim(stripslashes($_REQUEST['search']));
					$this->mSearchArray = explode(" ", $this->mSearchString);
				
				} else {
					header ("Location: /emptysearch/");
					die ();
				}
		}

 Changed tpl file to include {load_search_query assign="query"} & change the search query to {$query->value|escape:'htmlall'}.

 

It doesn't error with the [], running PCI scan now.....

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.