Archives de catégorie : Prestashop

Prestashop 1.x erreur « HTTP Error 503: temporarily overloaded »

Vous obtenez le message d’erreur « HTTP Error 503: temporarily overloaded »

L’erreur « HTTP Error 503: temporarily overloaded » sous-entend que le serveur sur lequel est hebergé votre site est surchargé.

Cependant, sous Prestashop 1.x, vous pouvez obtenir cette erreur dans des circonstances qui n’ont absolument rien à voir avec une surcharge serveur (chez Icodia ce message d’erreur n’existe pas sur nos serveurs) :

Lorsque vous  bloquez l’accès à votre site à certains pays, Prestashop se base sur les provenances des IPs et redirige les utilisateurs vers une page spécifique qui vous renvoie ce message incriminant la charge serveur (alors que ce n’est pas le cas) :

/* Display a specific page if the user country is not allowed */
 protected function displayRestrictedCountryPage()
 {
 header('HTTP/1.1 503 temporarily overloaded');
 $this->context->smarty->assign('favicon_url', _PS_IMG_.Configuration::get('PS_FAVICON'));
 $this->smartyOutputContent(_PS_THEME_DIR_.'restricted-country.tpl');
 exit;
 }

Cela peut avoir des conséquences diverses, comme par exemple un souci pour la validation W3C de votre site ou de votre flux RSS :

Effectivement, le site du W3C  a ses IPs basées principalement aux Etats Unis, si vous avez donc bloqué l’accès à cette région, Prestashop va rediriger le W3C vers ce message qui incrimine la charge serveur, alors qu’il s’agit simplement du blocage des IP américaines.

Comment corriger ce souci ?

Option 1 :

Vous pouvez fixer simplement en désactivant le module de blocage par localisation d’ip de Prestashop ou autoriser en plus les pays en lien avec vos tests

Option 2 :

Sinon modifier le paramètre _PS_GEOLOCATION_NO_CATALOG_ dans votre fichier defines.inc.php et le passer à 1. Cela aura pour conséquence de désactiver le module de blocage par pays sur le catalogue du CMS.

Fix UnZip Prestashop

Ce problème est intervenu sur la version 1.5 et suivantes. Les archives mises à disposition par Prestashop pour le CORE comme pour les modules sont encapsulées avec des fichiers qui ont des droits en 644, et donc sans droit d’exécution. Quand PHP est en module d’Apache, cela ne pose pas de problème. Quand il est en CLI comme sur notre plateforme (seule réelle solution pour le sécuriser), c’est plus embêtant car les .PHP ne peuvent plus être exécutés. Il reste possible de mettre à jour les CHMOD après l’installation, mais chaque mise à jour de modules génère un nouveau problème de droits sans exécution, donc de script d’installation du module, pas de création des tables nécessaires au module, etc.

Nous proposons la modification suivante pour ces versions :

Dans le fichier /classes/Tools.php, fonction ZipExtract :

remplacer :

public static function ZipExtract($from_file, $to_dir)
	{
		if (!file_exists($to_dir))
			mkdir($to_dir, 0777);
		if (class_exists('ZipArchive', false))
		{
			$zip = new ZipArchive();
			if ($zip->open($from_file) === true && $zip->extractTo($to_dir) && $zip->close()){
				return true;
			}
			return false;
		}
		else
		{
			require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php');
			$zip = new PclZip($from_file);
			$list = $zip->extract(PCLZIP_OPT_PATH, $to_dir, PCLZIP_OPT_REPLACE_NEWER);
			foreach ($list as $file)
				if ($file['status'] != 'ok' && $file['status'] != 'already_a_directory')
					return false;
			return true;
		}
	}

Par :

public static function ZipExtract($from_file, $to_dir)
	{
		if (!file_exists($to_dir))
			mkdir($to_dir, 0777);
		if (class_exists('ZipArchive', false))
		{
			$zip = new ZipArchive();
			if ($zip->open($from_file) === true && $zip->extractTo($to_dir) && $zip->close()){
				// Debut fix ICODIA
				@Tools::chmodr($to_dir, 0777);
				// Fin fix ICODIA
				return true;
			}
			return false;
		}
		else
		{
			require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php');
			$zip = new PclZip($from_file);
			$list = $zip->extract(PCLZIP_OPT_PATH, $to_dir, PCLZIP_OPT_REPLACE_NEWER);
			foreach ($list as $file)
				if ($file['status'] != 'ok' && $file['status'] != 'already_a_directory')
					return false;
			return true;
		}
	}

Analyse des requêtes SQL sous Prestashop

Si votre boutique Prestashop est lente, il vous faut rapidement identifier l’origine de cette lenteur.

Cela peut parfois être, par exemple, une requête SQL qui pose problème.

Pour cela, une modification simple permet d’écrire dans un fichier (journal ou log) des informations sur les requêtes effectuées (requête, durée, nombre de requête total, durée totale cumulée de l’ensemble des requêtes, etc.).

Cette procédure est très utilisée par notre support pour identifier un problème et est évidement transposable à de nombreux autre CMS.

Elle est systématiquement déployée sur les environnements de développement ou de test sur les sites dont nous assurons l’infogérance, dans une version plus complexe, qui journalise les données par page, avec des contextes définis qui permettent de comparer des systèmes de cache par exemple, calcule des moyennes, etc.
En bref, elle donne de très nombreuses pistes d’optimisation de la boutique.

Il est indispensable de limiter la journalisation à une IP (la vôtre) si vous utilisez cette solution sur un environnement en production, car le journal peut très rapidement prendre du poids et parce que les données seront moins facile à exploiter avec plusieurs visiteurs simultanés. Il est également important de désactiver le système de journalisation et d’effacer le journal après les tests.

Dans le fichier /classes/Db.php, ligne 318 environ, remplacer la fonction query() par :

public function query($sql)
	{
		if ($sql instanceof DbQuery)
			$sql = $sql->build();

		if($_SERVER["REMOTE_ADDR"]=="1.2.3.4") { // remplacer 1.2.3.4 par votre IP publique
			global $icochrono;
			$icochrono = microtime(true);
		}
		$this->result = $this->_query($sql);
		if($_SERVER["REMOTE_ADDR"]=="1.2.3.4") { // remplacer 1.2.3.4 par votre IP publique
			global $_SERVER,$icochrono, $iconbreq, $icototalreq;
			$iconbreq++;
			$chrono = microtime(true) - $icochrono;
			$build = $icochrono - $icochrono2;
			$icototalreq += $chrono;
			file_put_contents("icolog", "[".$iconbreq.". ".date("d/m/Y H:i:s")." / ".round($chrono*1000, 2)." ms / total : ".round($icototalreq*1000, 2). " ms] ".trim(str_replace("\n", " ", $sql))."\n", FILE_APPEND);
		}
		if (_PS_DEBUG_SQL_)
			$this->displayError($sql);
		return $this->result;
	}

Le fichier de journalisation est créé en racine du site, il s’appelle « icolog ».

Prestashop – Module ATOS – Bug sur les URLs de retour

Le module ATOS utilise deux binaires pour encrypter (REQUEST) les paramètres d’un paiement pour les envoyer à l’interface de la banque et pour décrypter le retour du terminal de paiement (RESPONSE).
Lors de la préparation de la chaîne encryptée qui est postée sur le TPE par le formulaire d’accès (les logos des différents types de cartes bancaires), le module prépare une chaîne de paramètres séparés par des espaces qui est passé en argument lors de l’exécution du binaire REQUEST.

Or, ces paramètres contiennent des URL (de retour, de réponse automatique, d’annulation) dans lesquelles sont passées dynamiquement des variables en GET (session, etc.)
Les caractères de séparation utilisés (& et ?) doivent être échappés pour être correctement transmis au binaire.

Le module ne le faisant pas, les liens de retour à la boutique sont incorrects, les « ? » et « & » sont précédés d’un « \ ».

Pour corriger ce bug, il suffit de mettre ces caractères entre double-quotes avant de passer la chaîne au binaire :

Dans le fichier atos.php, ligne 223 environ, remplacer :

// Do not add \n or something else
$parm = 'merchant_id='.Configuration::get('ATOS_MERCHANT_ID').' language='.$lang->iso_code.' customer_id='.intval($cart->id_customer).' caddie='.intval($cart->id).' merchant_country=fr amount='.(int)round(sprintf('%f', $cart->getOrderTotal() * 100)).' currency_code='.$currency_num.' pathfile="'.dirname(__FILE__).'/pathfile" normal_return_url="'.$returnPage.'" cancel_return_url="'.$cancelPage.'" automatic_response_url="'.$ipnPage.'" customer_ip_address='.$_SERVER['REMOTE_ADDR'].$redirect;

par :


// Do not add \n or something else
$parm = 'merchant_id='.Configuration::get('ATOS_MERCHANT_ID').' language='.$lang->iso_code.' customer_id='.intval($cart->id_customer).' caddie='.intval($cart->id).' merchant_country=fr amount='.(int)round(sprintf('%f', $cart->getOrderTotal() * 100)).' currency_code='.$currency_num.' pathfile="'.dirname(__FILE__).'/pathfile" normal_return_url="'.$returnPage.'" cancel_return_url="'.$cancelPage.'" automatic_response_url="'.$ipnPage.'" customer_ip_address='.$_SERVER['REMOTE_ADDR'].$redirect;
/* Bugfix Icodia */
$parm = str_replace("?", "\"?\"", $parm);
$parm = str_replace("&", "\"&\"", $parm);
/* Fin bugfix Icodia */