Here is an apache2 htaccess example that prevents the downloading of phar-Archives by the user:
RewriteEngine on
RewriteRule ^(.*)\.phar$ - [F]
It triggers a "403 - Forbidden" message instead of delivering the archive.L'extension phar fournit un moyen de mettre une application PHP complète dans un fichier unique appelé un "phar" (PHP Archive) pour une installation et une configuration aisées. En plus de ce service, l'extension fournit aussi une classe d'abstraction de format de fichier pour créer et manipuler des fichiers tar et zip à travers la classe PharData, tout comme PDO fournit une interface unifiée pour accéder à des bases de données différentes. Mais à l'inverse de PDO, qui ne peut pas transposer les données d'une base à l'autre, Phar a la possibilité de convertir des fichiers tar, zip et phar avec une simple ligne de code. Regardez Phar::convertToExecutable() pour avoir un exemple.
Qu'est-ce que phar? Les archives phar sont en fait un moyen pratique de grouper plusieurs fichiers en un seul. Ainsi, une archive phar permet de distribuer une application PHP complète dans un fichier unique et de l'exécuter à partir de ce fichier sans pour autant l'extraire sur le disque. De plus, des archives phar peuvent être exécutées par PHP aussi facilement que n'importe quel autre fichier, aussi bien en ligne de commande que via un serveur web. Phar est une sorte de clé USB pour les applications PHP.
Phar implémente cette fonctionnalité via un flux. Normalement, pour utiliser un fichier externe à partir d'un script PHP, il faut utiliser la fonction include:
Exemple #1 Utiliser un fichier externe
<?php
include '/chemin/vers/le/fichier/externe.php';
?>
On peut considérer que PHP traduit en fait
/chemin/vers/le/fichier/externe.php en un
flux file:///chemin/vers/le/fichier/externe.php, et qu'il
utilise de façon cachée les fonctions de flux de fichiers plats pour accéder
à des fichiers locaux.
Pour utiliser un fichier nommé fichier.php contenu dans une archive phar
/chemin/vers/monphar.phar,
la syntaxe est quasi similaire à la syntaxe file:// ci-dessus.
Exemple #2 Utiliser un fichier contenu dans une archive phar
<?php
include 'phar:///chemin/vers/monphar.phar/fichier.php';
?>En fait, on peut traiter une archive phar comme s'il s'agissait d'un disque externe, en utilisant n'importe laquelle des fonctions relatives à fopen(), opendir() et mkdir() pour lire, changer ou créer des nouveaux fichiers ou répertoires au sein de l'archive phar. Cela permet à des applications PHP complètes d'être distribuées dans un seul fichier et d'être exécutées à partir de celui-ci
L'utilisation la plus courante d'une archive phar est de distribuer une application complète en un seul fichier. Par exemple, l'installeur PEAR qui est inclus avec les versions de PHP est distribué grâce à une archive phar. Pour utiliser l'archive phar ainsi distribuée, celle-ci peut être exécutée via la ligne de commande ou via un navigateur web.
Les archives phar peuvent être distribuées sous forme de fichiers tar,
de fichiers zip ou de fichiers phar spécialement conçus
pour l'extension phar. Chaque format de fichier a ses avantages et ses inconvénients. Les fichiers
zip et tar peuvent être extraits par n'importe quel outil tiers qui peut lire le format, mais
requièrent l'extension phar pour être exécutés par PHP. Le format de fichier phar est unique et dédié
à l'extension phar et peut être créé uniquement par celle-ci ou par le paquet PEAR
» PHP_Archive, mais a l'avantage de ne pas
nécessiter l'installation de l'extension phar pour que l'application empaquetée puisse être exécutée.
En d'autres mots, même avec l'extension phar désactivée, il est possible d'exécuter ou d'inclure une archive basée sur phar. Accéder à des fichiers individuels au sein d'une archive phar n'est possible qu'avec l'extension phar à moins que l'archive phar n'ait été créée par PHP_Archive.
L'extension phar est aussi capable de convertir une archive phar à partir d'un tar vers un fichier zip ou phar en une seule commande :
Exemple #3 Convertir une archive phar au format tar
<?php
$phar = new Phar('monphar.phar');
$pgz = $phar->convertToExecutable(Phar::TAR, Phar::GZ); // produit monphar.phar.tar.gz
?>Phar peut compresser des fichiers individuels ou une archive entière en utilisant la compression gzip ou bzip2, et peut vérifier l'intégrité de l'archive automatiquement en utilisant des fonctions de signature MD5, SHA-1, SHA-256 ou SHA-512.
Enfin, l'extension phar est orientée sécurité, elle désactive par défaut les accès
en écriture sur les archives phar exécutables et requiert la désactivation au niveau système
du paramètre phar.readonly du php.ini pour créer ou modifier des archives phar.
Des archives tar et zip sans le marqueur exécutable peuvent toujours être créées ou modifiées
en utilisant la classe PharData.
Si l'on crée des applications dans le but des distribuer, il est recommandé de lire Comment créer des archives Phar. Pour davantage d'informations sur les différences entre les formats de fichier que phar supporte, il est recommandé de lire Phar, Tar et Zip.
Lors de l'utilisation des applications phar, il y a des astuces très utiles dans Comment utiliser des archives Phar.
Le mot phar est la contraction de PHP et de
Archive et est grandement inspiré
du mot jar (Java Archive) familier aux développeurs Java.
L'implémentation des archives Phar est basée sur le paquet PEAR » PHP_Archive, et les détails d'implémentations sont les mêmes, bien que l'extension Phar soit plus puissante. En plus, celle-ci permet à la plupart des applications PHP d'être exécutées sans modification alors que les archives basées sur PHP_Archive requièrent souvent beaucoup de modifications pour fonctionner.
Here is an apache2 htaccess example that prevents the downloading of phar-Archives by the user:
RewriteEngine on
RewriteRule ^(.*)\.phar$ - [F]
It triggers a "403 - Forbidden" message instead of delivering the archive.If you get blank pages when trying to access a phar web-page, then you probably have Suhosin on your PHP (like in Debian and Ubuntu), and you need to ad this to your php.ini to allow execution of PHAR archives :
suhosin.executor.include.whitelist="phar"Users should set the `sys_temp_dir` directive.
PHAR stores temporary files in either `sys_temp_dir` or the current working directory(CWD).
This is especially important if you're CWD is on a remote file system. Often web server clusters will share a common file system between each web server (using NFS, DFS, etc...). In such scenarios, if you don't set `sys_temp_dir` to a local directory, PHAR will be creating temporary files over the network, which will result in performance and functionality problems.Here is a very simple program for creating phar files with CLI. Note that it requires phar.readonly in php.ini set to false (Off).
<?php
$filename = "default";
$dir = "./";
$regex = "/^(?!.*build\\.php)(?:.*)$/";
$main = "main.php";
$shebang = "#!/usr/bin/env php";
$chmod = true;
for ($i = 0; $i < $argc; $i++) {
switch ($argv[$i]) {
case "-o":
$i++;
if ($i >= $argc) {
echo "Missing output file name" . PHP_EOL;
exit(1);
}
$filename = $argv[$i];
break;
case "-i":
$i++;
if ($i >= $argc) {
echo "Missing input directory name" . PHP_EOL;
exit(1);
}
$dir = $argv[$i];
break;
case "-p":
$i++;
if ($i >= $argc) {
echo "Missing regular expression pattern" . PHP_EOL;
exit(1);
}
$regex = $argv[$i];
break;
case "-m":
$i++;
if ($i >= $argc) {
echo "Missing main file" . PHP_EOL;
exit(1);
}
$main = $argv[$i];
break;
case "-b":
$i++;
if ($i >= $argc) {
echo "Missing shebang of file" . PHP_EOL;
exit(1);
}
$shebang = $argv[$i];
break;
case "--no-chmod":
$chmod = false;
break;
}
}
if (file_exists($filename)) unlink($filename);
$phar = new Phar($filename);
$phar->buildFromDirectory($dir, $regex);
$phar->setStub(($shebang ? $shebang . PHP_EOL : "") . $phar->createDefaultStub($main));
if ($chmod) {
chmod($filename, fileperms($phar) | 0700);
}when read via phar://, stream will unserialize object including phar file
Use this to create phar
<?php
// create new Phar
$phar = new Phar('lemon.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');
// add object of any class as meta data
class AnyClass {}
$object = new AnyClass;
$object->data = 'Chanh';
$phar->setMetadata($object);
$phar->stopBuffering();
?>
and read it by:
<?php
class AnyClass {
function __destruct() {
echo $this->data;
}
}
// output: Chanh
file_get_contents('phar://test.phar');
?>Here is a very simple class to build a phar file from a given source directory. You can use this for your own project and simple deployment.
But my main goal was to show how to use PHAR functions in a simple way.
<?php
class BuildPhar
{
private $_sourceDirectory = null;
private $_stubFile = null;
private $_outputDirectory = null;
private $_pharFileName = null;
/**
* @param $_sourceDirectory // This is the directory where your project is stored.
* @param $stubFile // Name the entry point for your phar file. This file have to be within the source
* directory.
* @param null $_outputDirectory // Directory where the phar file will be placed.
* @param string $pharFileName // Name of your final *.phar file.
*/
public function __construct($_sourceDirectory, $stubFile, $_outputDirectory = null, $pharFileName = 'myPhar.phar') {
if ((file_exists($_sourceDirectory) === false) || (is_dir($_sourceDirectory) === false)) {
throw new Exception('No valid source directory given.');
}
$this->_sourceDirectory = $_sourceDirectory;
if (file_exists($this->_sourceDirectory.'/'.$stubFile) === false) {
throw new Exception('Your given stub file doesn\'t exists.');
}
$this->_stubFile = $stubFile;
if(empty($pharFileName) === true) {
throw new Exception('Your given output name for your phar-file is empty.');
}
$this->_pharFileName = $pharFileName;
if ((empty($_outputDirectory) === true) || (file_exists($_outputDirectory) === false) || (is_dir($_outputDirectory) === false)) {
if ($_outputDirectory !== null) {
trigger_error ( 'Your output directory is invalid. We set the fallback to: "'.dirname(__FILE__).'".', E_USER_WARNING);
}
$this->_outputDirectory = dirname(__FILE__);
} else {
$this->_outputDirectory = $_outputDirectory;
}
$this->prepareBuildDirectory();
$this->buildPhar();
}
private function prepareBuildDirectory() {
if (preg_match('/.phar$/', $this->_pharFileName) == FALSE) {
$this->_pharFileName .= '.phar';
}
if (file_exists($this->_pharFileName) === true) {
unlink($this->_pharFileName);
}
}
private function buildPhar() {
$phar = new Phar($this->_outputDirectory.'/'.$this->_pharFileName);
$phar->buildFromDirectory($this->_sourceDirectory);
$phar->setDefaultStub($this->_stubFile);
}
}
//END Class
//Example Usage:
$builder = new BuildPhar(
dirname(__FILE__).'/_source',
'my_default_stub.php',
dirname(__FILE__).'/_output',
'my-phar-file.phar'
);