Schplurtzeries
Le wiki de schplurtz
Dokuwiki

20. June 2012 [fonctionarray_fill_keys] ztrulphcs

php chez free

J'avais cherché des infos sur PHP chez free, mais je m'étais arrêté sur un wiki de free, devenu vide depuis. Maintenant j'ai trouvé tout certains renseignements ici. Mais pas tout, non. On y trouve une partie de ce qui ne fonctionne pas, mais pas la manière de contourner les problèmes que cela engendre. L'une des conséquences de la mutilation modification de PHP par free est que Dokuwiki ne peut pas s'installer sans modifications, pas plus, d'ailleurs, qu'aucune application PHP dont la taille dépasse «Hello-World.php». D'autre part, on ne peut pas tout mettre dans un fichier .htaccess chez free, ou ce qu'il faut y mettre est plutôt inattendu. Je recense ici les problèmes rencontrés lors de l'installation d'un dokuwiki chez free, ainsi que les contournements trouvés. Mais les conseils donnés ici ne sont pas spécifiques à dokuwiki; les limitations de php s'appliquent à toutes les applications écrites en PHP.

Références :

Cette page indique comment modifier en général les applications PHP pour qu'elles puissent fonctionner. les informations données ici devraient vous aider à résoudre les problèmes que vous pourriez rencontrer. Je suis loin d'être un spécialiste de PHP, il est donc possible que je n'ai pas envisagé les bonnes solutions aux problèmes rencontrés. Cela dit, je ne vois pas vraiment comment faire autrement que de modifier les applications qui ne fonctionnent pas, vu que les fonctions rename_function et override_function ne sont pas disponibles chez free.

En ce qui concerne Dokuwiki, J'ai écrit cette autre page qui explique comment mettre en œuvre manuellement les contournements indiqués ici. D'autre part l'outil liberatator effectue les modifications indiquées automatiquement; il est valable pour toutes les versions de DokuWiki.

Une dernière chose, globalement, je ne peux pas trop me plaindre, vu que je ne verse pas un centime à free et qu'en retour j'ai un hébergement sans la moindre publicité…

Bonne lecture

version de PHP

Par défaut, php 4 est activé. Le wiki de free1) précise qu'il suffit, pour activer php 5, de créer un fichier .htaccess contenant au moins cette ligne là

php 1

Remarquez que cette page2) du wiki de free préconise d'utiliser php 5. J'ai pas essayé, mais ça marche avec php 1.

On peut créer ce fichier à la racine du site, pour activer globalement php 5, ou dans le répertoire de l'application PHP pour n'activer php 5 que pour cette application si on l'a installé dans un sous répertoire.

J'ai créé ce fichier, et voilà la version de php qui fonctionne pour moi

solution pour version

Le mieux est d'activer php 5 pour tout le site, et donc de créer un fichier .htaccess à la base de son espace web.

sessions

Pour que les sessions PHP fonctionnent – et c'est indispensable pour les «grosses» applications, il faut un répertoire sessions à la racine du site web. quelque soit le sous répertoire où l'application est déployée.

solution pour session

Créer un répertoire sessions à la racine du site web.

include_path

On ne peut pas changer l'include_path, sans doute pour ne pas pouvoir inclure de fichiers d'un autre internaute, ou lire des fichiers système.

La fonction set_include_path ne fait rien du tout, mais ne retourne pas d'erreur.

L'include_path disponible est

votre_foyer/include:.:/usr/php5/lib/php

Soit, par exemple, pour un utilisateur toto :

/mnt/342/sda/2/z/toto/include:.:/usr/php5/lib/php

Solutions pour include_path

Plusieurs solutions sont possible dans ce cas,

  • Dans les fichiers .php, toujours indiquer un chemin aux fonctions include, include_once, require et require_once
  • Créer un répertoire include à la racine du site web et y installer tous les fichiers devant être inclus.
  • installer les fichiers devant être inclus dans le même répertoire que le fichier utilisant les fonctions include, include_once etc…

.htaccess

  1. On ne peut pas utiliser la directive php_value qui permet de configurer php. Si on utilise cette directive, le serveur web renvoie immédiatement une erreur 500 internal error. C'est tout de même un peu embettant car on ne peut pas configurer php;.
    Personnellement, je me répète, je ne paye pas un centime et j'ai tout de même un hébergement sans aucune pub. On va pas se plaindre, quand même.
  2. La syntaxe pour protéger un dossier par mot de passe est peu courante. La plupart des utilitaires PHP ne la connaisse pas et ne peuvent pas la générer. Si vous devez protéger certains dossiers par mot de passe, faite le à la main en respectant cette syntaxe3)cette syntaxe. Vous pouvez aussi utiliser ce mini gestionnaire de fichier adapté à free.
  3. On peut utiliser des directives conditionnelles. Supposons, que vous ayez le même fichier .htaccess chez free et chez un autre hébergeur, la différence de syntaxe va vous embêter. Utilisez alors des <ifDefine Free> dans le fichier. Par exemple, pour activer PHP 5, vous pouvez mettre le code suivant dans le fichier .htaccess .Chez free, cela activera la directive PHP 1, mais pas la directive zorglub. Ailleurs, la directive zorglub sera active mais pas la directive PHP 1. Merci à Charles pour son commentaire sur http://permalink.gmane.org/gmane.comp.web.spip.user/169140.
    .htaccess.exple
    <ifDefine Free>
     PHP 1
    </ifDefine>
    <ifDefine !Free>
     Zorglub
    </ifDefine>

fonction glob()

Pour une raison mystérieuse4), la fonction php glob() ne fonctionne pas !!

glob ne fait pas partie de la terrible liste des fonctions interdites.

contournement pour glob()

Il faudra modifier tous les fichiers PHP qui contiennent un appel à glob en remplaçant ces appels par des appels à une autre fonction équivalente. J'utilise la fonction myglob(). Cette fonction ne réagit pas tout à fait comme la vraie fonction glob mais elle est suffisante dans la plupart des cas. En particulier, elle ne prend pas en compte les variantes GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR et GLOB_ERR. De plus, son comportement diffère légèrement en ce qui concerne les liens symboliques pointant vers des fichiers cachés 5), mais cela n'a par contre strictement aucune importance car on ne peut pas créer de liens symboliques chez free. Au besoin, google sera votre ami. Enfin, myglob( '*' ) ou autre modèle sans chemin reverra des choses comme ./nom-fichiers, alors que la vraie glob, renvoie simplement nom-fichiers. Là encore cela n'a aucune importance puisque ./nom-fichier est équivallent à nom-fichier en ce qui concerne la désignation des fichiers; au pire un logiciel pourrait afficher un truc un peu moche comme /a/b/./fichier, mais cela reste équivallent à /a/b/fichier. Le risque est très faible

fonction myglob()

fonction rmdir()

Pour une raison mystérieuse, la fonction php rmdir() ne fonctionne pas ! Autrement dit, aucune application PHP ne peut détruire un quelconque dossier.

rmdir fait partie de la terrible liste des fonctions interdites.

contournement pour rmdir()

En fouillant un peu le web, on trouve que la fonction rename( $a, $b ) peut parfaitement renommer le dossier $a en $b. Jusque là rien d'incroyable. Mais si $b existe déjà, rename va quand même réussir. Et donc d'autres avant moi ont déjà trouvé qu'on peut facilement écrire une fonction myrmdir() qui après avoir vérifié la vacuité d'un dossier va le renommer en un nom fixe et convenu à l'avance, tel que poubelle par exemple. Le résultat tout net est qu'on a un dossier appelé poubelle à la racine du site, qu'on en aura jamais qu'un seul et qu'on peut “détruire” ainsi des dossiers avec PHP et cette fonction.

fonction myrmdir()

fonction umask()

umask fait partie de la terrible liste des fonctions interdites.

La fonction umask qui rentourne et fixe la valeur des autorisations à enlever par défaut lors de la création de fichiers et dossiers retourne une chaine vide et est sans effet. du code standard comme cet exemple tiré de eXtexplorer ne peut tout simplement plus fonctionner, car alors ~ & 0111 n'est pas une expression PHP valide.

// make file executable, obey umask
$mode = fileperms($v_header['filename']) | (~umask() & 0111);

contournement pour umask()

Pour les appels à umask($nouvelle_valeur) il n'y a aucun contournement possible. la fonctionnalité n'est pas disponible. Point. De toute manière elle ne présente pas grand intérêt chez free où chaque site web a son système de fichiers isolé des autres, est mono-utilisateur avec un seul utilisateur possible : l'utilisateur web.

Ce qu'on peut faire pour rendre les expressions valide, et faire en sorte que le programme n'ait plus d'erreur de syntaxe, est remplacer tous les appels à umask() et les appels à umask( blablabla ) par une valeur habituelle d'umask, comme 022 par exemple. Le code ci dessus devient alors :

// make file executable, obey umask
$mode = fileperms($v_header['filename']) | (~022 & 0111);

La fonction umask(), par nature, sera appelée seulement quelques fois dans tout un programme. Le plus simple est de rechercher toutes les occurrences de cette fonction et faire systématiquement ces remplacements.

On peut également écrire une fonction myumask() et remplacer tous les appels à umask() par des appels à myumask(). La fonction myumask() n'a aucun effet sinon de toujours retourner une valeur convenable pour un tel masque.

fonction ''myumask()''

fonction opendir()

Pour une raison mystérieuse, la fonction php opendir() échoue avec un warning si un répertoire n'existe pas, et ce, même lorsqu'elle est appelée comme ceci @opendir(…) .

contournement pour opendir()

On peut utiliser une fonction myopendir() et modifier tous les fichiers php pour qu'ils utilisent cette nouvelle fonction. C'est un peu overkill, car la plupart du temps, opendir porte sur un répertoire qui existe.

Plutôt que de faire un remplacement systématique, on peut ne faire le remplacement que pour les cas qui produisent une erreur. On est alors averti par un message de PHP du fichier et de la ligne qui a posé un problème.

fonction myopendir

fonction usleep()

Cette fonction qui permet d'attendre le nombre spécifié de microsecondes n'a aucun effet. Elle ne retourne pas d'erreur, c'est déjà ça, mais ne sert absolument à rien. NB elle fait partie de la terrible liste des fonctions interdites

Pas de contournement trouvé pour le moment…

fonction array_fill_keys()

Comme me l'a signalé Damien Gaignon, la fonction array_fill_keys n'existe pas chez free puisque cette fonction n'est disponible qu'avec les versions de PHP >= 5.2 et que la version de PHP en service à ce jour6) est 5.1.trucmuche.

Bon ben c'est pas bien grave. sauf que certains logiciels ont vraiment envie/besoin de cette fonction et qu'ils meurent avec ce message d'erreur

Fatal error: Call to undefined function array_fill_keys()

quand leur code PHP tente de faire appel à cette fonction. Au passage, puisque ma préoccupation est principalement dokuwiki, sachez que le greffon plugin:translation fait appel à cette fonction.

La solution est d'en écrire une version en PHP. il suffira de rajouter le code dans les fichiers qui y font appel.

solution pour fonction array_fill_keys()

:!: Attention on trouve plein de versions en PHP de cette fonction en parcourant le web, nombreuses sont celles qui ne se comportent pas comme il faut. La faute peut-être – mais pas sûr – à bananasims qui dans ce premier post chez PHP en propose une version… erronée7). La vraie bonne solution pour émuler cette fonction est décrite par matrebatre dans le même fil ici et utilise cette formule toute simple :

array_combine($keys,array_fill(0,count($keys),$value))

Voilà donc ma version, basée sur ce code, vérifiée avec un PHP 5.3 et qui a permis de faire fonctionner correctement le greffon translation de dokuwiki. Notez au passage que le code est enveloppé dans un test if(!function_exists('array_fill_keys')), ce qui évitera les erreurs le jour où free passera à une version supérieure de PHP.

array_fill_keys.php
if(!function_exists('array_fill_keys')) {
function array_fill_keys($keys, $value = '') {
 return is_array($keys) ?
   array_combine($keys,array_fill(0,count($keys),$value))
   : null;
}
}

Absence de connexion vers l'extérieur

Pour, moi, depuis quelque chose comme fin août 2011 environ8), PHP ne peut plus effectuer de connexion à des sites externes. Les outils du genre ”mise à jour automatique”, ”installation de greffons” ou ”agrégateur de flux” ne fonctionnent plus. La raison en serait que free tente de faire disparaitre ainsi les redirecteurs et autres serveur mandataires installés par de petits malins…

Si vos scripts se connectent toujours à la même adresse, vous pouvez demander sur le forum usenet de free proxad.Free.services.pagesperso la mise en liste blanche de certaine adresse. Pour les détails sur l'art et la manière de faire ce genre de demande, prenez le temps de lire l'article des pages perso qui traite du sujet. Il parait que les mecs qui peuvent intervenir chez free lisent de temps en temps ces news, ne répondent – quand ils répondent – que par phrases courtes (à la limite de la brusquerie), qu'une non réponse vaut pour un refus9), etc… Bref, free en a rien à foutre de vos problèmes, les mecs qui peuvent intervenir usent sans états d'âme de leur pouvoir. Ce forum est plutôt rude. Je le répète, lisez donc et relisez l'article des pages perso et ne gâchez pas votre unique chance de voir débloqué l'URL qui vous intéresse tant.

NB
Le problème semble se déclencher de manière plus où moins aléatoire chez certains internautes. J'ai pu pendant presqu'un an télécharger depuis le serveur de free des greffons pour mon site web. Je ne peux plus…

NB2
Avant cela, lorque PHP pouvait se connecter à des sites externes, de toute façons, il existait une petite restriction concernant les connexions. Comme openssl et TLS ne sont pas inclus dans PHP chez free, PHP ne peut pas ouvrir de flux https. Demander à PHP de télécharger des fichiers depuis des sites en https, comme github par exemple est donc impossible.

Référence 1

http://forum.sfgame.fr/showthread.php?t=5711&page=5

Texte reproduit ici

Référence 2
Référence 3

Traitement des images

La bibliothèque GD est présente, installée et tout semble OK. Oui, mais non. Est-ce lié à la quantité de mémoire max disponible pour PHP ou à autre chose, je ne saurai le dire. Toujours est-il qu'il existe une limite à la taille des images qu'on peut manipuler, retailler, annoter etc… La taille limite est aux environs de 2600×2000 pixels. En dessous pas de problème, au delà, impossible. Ça pose problème avec les images des appareils photo modernes qui sont bien plus grandes…

Avec DokuWiki, qui utilise la bibliothèque GD, J'ai fait des tests simples. pour des images de taille de plus en plus grande, j'essaie de redimensionner vers une image de 200 pixels de large, et je vois bien quand ça plante…

  • Pour des tailles d'origine jusqu'à 2592×1944, pas de problème CF maxsize_45 maxsize_50, maxsize_55 et maxsize_60
  • pour une taille de 2808×2106, ça fonctionne pas du tout CF maxsize_65
  • pour des tailles supérieures, ça fonctionne pas, mais l'image d'origine est renvoyée. CF maxsize_70, maxsize_75, maxsize_80, maxsize_85, maxsize_90, et maxsize_95.
    • envoie très long qui peut provoquer un arrêt par déclenchement de la minuterie (timeout en bon anglais)
    • Le fichier reçu par le navigateur est très gros et le navigateur doit faire le redimmensionnement lui même, ce qu'il fait mal (au moins FF) et l'image est moche
    • Le navigateur peut consommer énormément de mémoire. cela dépend du navigateur

contournement pour image

Si vous rencontrez des problèmes lors du traitement des images, réduisez leur taille avant de les envoyer chez free.

Temps d'exécution et mémoire ?

D'autre problèmes surviennent sans qu'il soit possible de vraiment savoir… Est-ce que le temps d'exécution d'un script est dépassé, ou bien s'agit-il d'un dépassement de mémoire, ou encore a-t-il atteint une sorte de quota réseau ?

contournement temps et mémoire

rien

schplurtz le déboulonné 2011/01/24 21:10

1) , 2) , 3) page devenue vide…
4) en fait, comme indiqué ici, c'est probablement pour cette raison
5) les fichiers dont le nom commence par un point (.)
6) 2012-06-20
7) ces vraies fausses bonnes fonctions n'ont d'autres avantages que d'éviter les erreurs fatales de PHP. Mais leur comportement ne permet pas aux fonctionnalité du logiciel qui en a besoin de fonctionner normalement. ie le code PHP compile sans erreur, mais la partie concernée de l'application est toujours défectueuse.
8) date vraiment variable apparemment, ça pourrait remonter à janvier 2010 d'après ce que j'ai trouvé sur le web
Voir à ce propos les dates de la première référence et de la troisième.
9) Comment fait-on dans ce cas pour savoir si le type à vu le post ou pas ? mystère…