2011-06-14 23:09

La fonction PHP escapeshellarg dépend de votre locale courante. Je pense que c’est mal, mais les développeurs de PHP on fait ce choix. Si comme moi votre locale par défaut est ‘C’, vous perdez vos caractères UTF8.

Ils suggèrent d’utiliser quelque chose comme setlocale(LC_CTYPE, "en_US.UTF-8"). Ça ne fonctionne pas si la locale en_US.utf8 n’est pas installée sur votre système. Bien sûr vous avez peut-être fr_FR.utf8, ou de_DE.utf8, mais vous aller devoir toutes les essayer jusqu’à trouver une locale utf8 qui correspond. Et s’il n’y en a pas vous êtes foutus. C’est mauvais aussi si vous voulez du code qui marche partout.

Utilisez simplement :

$escapedArg = "'".str_replace("'", "'\\''", $arg)."'";

Ça fait la même chose que la fonction escapeshellarg : remplacer chainel'hyperlongue par

'chainel'\''hyperlongue'

comme décrit dans le manuel de escapeshellarg (et j’ai aussi jeté un œil au code source de PHP pour être sûr).

Voir aussi :

2011-06-14 23:09 · Tags: , ,
2010-10-30 16:50

Pour la gallerie d’images php Bizou, j’ai cherché différentes manière de précharger l’image suivante pour le mode “visualisation” (exemple).

Sous Firefox, c’est très simple. Il suffit d’utiliser la balise suivante pour que le navigateur précharge les contenus indiqués.
Les contenus sont préchargés en arrière-plan une fois que la page courante est chargée intégralement.

 [html]
<link rel="prefetch" href="/images/nextimage.jpg" />

Sauf que pour le moment seul Firefox supporte cette fonctionnalité.
Note : un ticket est ouvert sur le sujet pour le projet Chromium.

Pour les autres navigateurs que Firefox, il faut utiliser du Javascript déclenché à l’événement window.onload :

 [javascript]
<script type="text/javascript">
window.onload = function() {
    // pour les images
    var im = new Image();
    im.src = '/images/nextimage.jpg';
    // et pour les autres contenus
    var req = new XMLHttpRequest();
    req.open('GET', 'nextpage.php', false);
    req.send(null);
};
</script>

Attention aux en-têtes HTTP de cache envoyés par le serveur vers le navigateur.
Pour un préchargement efficace de page PHP, il faudra que votre script envoie un en-tête Expires.

header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));

Enfin, pour une détection simple du navigateur depuis le script PHP :

<?php if (strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== false) { ?>
<link rel="prefetch" href="nextpage.php" />

<?php } else { ?>
<script type="text/javascript">
window.onload = function() {
    var req = new XMLHttpRequest();
    req.open('GET', 'nextpage.php', false);
    req.send(null);
};
</script>
<?php } ?>

Liens :

2010-10-30 16:50 · Tags: , , , , ,
2008-06-19 08:30

En TMA, on voit de tout, pour le meilleur ou pour le pire. Le meilleur ayant cependant tendance à se faire rare. Ou peut-être est-ce du à la loi de Murphy ?

Voici quelques extraits de code PHP relevé par notre ami Teeboo, à déguster…

Les commentaires valent leur pesant de cacahuètes :

if(isset($t[2]) && $t[2] !== null) // Empiriquement, j'ai vu que c'était équivalent, mais sait-on jamais…
/* Accesseur tordu permettant à un compte qui s'est laissé expirer puis en
* catastrophe a voulu se réabonner, de jouir plus ou moins de son ancien
* abonnement. À utiliser avec prudence (autrement dit nulle part ailleurs
* que là où je l'ai déjà fait), l'idée qui a toujours été derrière les
* specs techniques étant que quelqu'un qui a laissé expirer son compte,
* c'est pour sa pomme, il faut qu'il se réabonne en partant de 0. Mais
* puisqu'il aura été décidé qu'on pardonne tout à l'utilisateur...
* Renvoie false le plus souvent possible, et true quand on est quasi-
* certain de notre coup; les erreurs de BdD renvoient du false aussi. */
function ComptePrimaireOuRecuperateur($pourPaquet)
/* À FAIRE: simplifier les paramètres. L'idée de départ de cette fonction
* était en fait d'externaliser un bout de VerifierInfos; elle table donc
* sur tout ce qui y a déjà été calculé, mais maintenant si on peut en faire
* une fonction indépendante, ce ne sera pas plus mal. */
    function DernieresAdresses($idChose, $mode, &$payeur, &$infos2)
// Si tous ses abonnements ont expiré, on tente notre chance avec un vieil abonnement. Pas terrible, sachant que le module était à l'origine prévu pour que si un utilisateur a laissé son compte expirer, ben tant pis pour lui, il recommence tout un processus d'abonnement. Notre permissivité nous perdra. /* BOGUE: ça permet à un utilisateur de laisser expirer son compte, puis de créer deux abonnements de remplacement dans la même journée. Pour peu que par mégarde les deux soient validés, ça va péter! */
$d = array();
$o = array(); // $d, mais d'origine. Alors qu'on adapte $d à usage de paramètres pour les fonctions qu'on appelera derrière, on garde $o tel quel pour le réinjecter en cas d'annulation de la procédure (formulaire mal rempli, etc.).

Note : Attention, là, c’est un gros morceau. Plusieurs perles se cachent là-dedans, saurez vous les retrouver ? Pour info, COMPTESADREL_DISPO est une constante définie plus haut, qui vaut 0.

else if(($eAdrel = CompteUtil::VerifierDispoAdrel($d[champAdrel])) != COMPTESADREL_DISPO || ($eAdrel = VerifFormUtil::checkExistingEmailAddress($d[champAdrel]) ? COMPTESADREL_PRESENTE : COMPTESADREL_DISPO) != COMPTESADREL_DISPO)
do
{
    switch ($eAdrel)
    {
        case COMPTESADREL_ERREUR:
            $e = 'Une erreur interne est survenue.'; /* À FAIRE: un message un peu plus bavard. */
            break;
        case COMPTESADREL_PRESENTE:
            $manquants[] = 'Adresse utilisée par un compte en cours d\'abonnement';
            //$emailDejaEnBase = true;
            break;
        case COMPTESADREL_PASSEE:
            $manquants[] = 'Adresse utilisée par un compte qui ne dispose plus d\'abonnement';
            $emailDejaEnBase = true;
            break;
        case COMPTESADREL_FUTURE:
        case COMPTESADREL_DEMANDEE:                             if(AUTORISER_DEUX_DEMANDES_MEME_ADREL) break 2; // Finalement pas erreur.

            $manquants[] = 'Adresse reservée pour un compte en cours de création';
            break;
    }
    if(!$e)
        $e = true;
    $tpl->setVariable('email_erreur', 1);
}
while(false);

}
if(!$e) do // Un do dont la sortie sera une erreur.
{
    $e = true; // On commence par signaler qu'il y a erreur: ce sera ce qui restera si on n'atteint pas la fin du while, où nous nous déclarerons exempts d'erreur.
if(!count($manquants)) // À FAIRE: un peu plus propre. Là c'est une récup' rapide un soir de bourre
/* ATTENTION: en mode INFOS_ACHAT, $idFacture doit être définie pour ici. *//* À FAIRE?: simplifier. C'est un résidu d'un ancien mode, où VerifierInfos sur les abo recevait un id_refernece comme $idChose, et sur les achats normaux un id_facture. Voir si on peut déduire $idFacture d'$idChose, si oui supprimer le dernier paramètre de VerifierInfos dont la valeur par défaut à false pourrait à tort laisser croire qu'on s'en fiche. Si on a du code pour déduire, dans un premier temps on pourra fonctionner en mode test où l'on compare le résultat de ce code et l'$idFacture effectivement passé, en laissant une trace si ça diffère. Si au bout d'un mois on n'a rien, on peut simplifier. Le cas où j'entrevois déjà un risque de différence est l'achat d'évolutions d'abonnement: si je me souviens bien, on a deux factures (facture d'abonnement - facture d'évolution) pour une seule référence (l'abonnement). */
/* Mutualisation de code, récupérée d'un code existant, ce qui peut
* expliquer l'inexplicable. */
function CloreEtapesFacturation(...
2008-06-19 08:30 · Tags: ,