PHP 8.5.0 Alpha 2 available for testing

Utilizar los archivos Phar : Introducción

Los archivos Phar son idénticos en concepto a los archivos JAR de Java, pero están diseñados específicamente para las necesidades y la flexibilidad de las aplicaciones PHP. Un archivo Phar se utiliza para distribuir una aplicación PHP completa o una biblioteca en forma de un único archivo. Una aplicación en forma de archivo Phar se utiliza exactamente de la misma forma que cualquier otra aplicación PHP:

php aplicacionesympa.phar
  

El uso de una biblioteca en forma de archivo Phar es el mismo que cualquier otra biblioteca PHP:

<?php
include 'bibliothequesympa.phar';
?>

El flujo phar proporciona el núcleo de la extensión phar, y es descrito en detalle aquí. El flujo phar permite el acceso a los ficheros contenidos en un archivo phar mediante las funciones estándar de ficheros fopen(), opendir(), y cualquier otra que funcione con ficheros normales. El flujo phar soporta todas las operaciones de lectura/escritura tanto en ficheros como en directorios.

<?php
include 'phar://bibliothequesympa.phar/fichero/interne.php';
header('Content-type: image/jpeg');
// los phars pueden ser alcanzados mediante la ruta completa o mediante alias
echo file_get_contents('phar:///ruta/completa/hacia/bibliothequesympa.phar/images/wow.jpg');
?>

La clase Phar implementa funcionalidades avanzadas para acceder a los ficheros y crear archivos phar. La clase Phar es descrita en detalle aquí.

<?php
try {
// abre un phar existente
$p = new Phar('bibliothequesympa.phar', 0);
// Phar extiende la clase DirectoryIterator de SPL
foreach (new RecursiveIteratorIterator($p) as $file) {
// $file es una clase PharFileInfo y heredada de SplFileInfo
echo $file->getFileName() . "\n";
echo
file_get_contents($file->getPathName()) . "\n"; // muestra el contenido;
}
if (isset(
$p['fichero/interne.php'])) {
var_dump($p['fichero/interne.php']->getMetadata());
}

// crea un nuevo phar - phar.readonly debe ser 0 en php.ini
// phar.readonly está activado por omisión por razones de seguridad.
// En servidores de producción, los Phars no necesitan ser creados,
// solo ejecutados.
if (Phar::canWrite()) {
$p = new Phar('nuevophar.tar.phar', 0, 'nuevophar.tar.phar');
// Se crea un archivo Phar basado en tar, comprimido por gzip (.tar.gz)
$p = $p->convertToExecutable(Phar::TAR, Phar::GZ);

// crea una transacción - nada se escribe en nuevophar.phar
// hasta que stopBuffering() sea llamado, aunque se requiere almacenamiento temporal
$p->startBuffering();
// añade todos los ficheros de /ruta/hacia/elproyecto en el phar con el prefijo "proyecto"
$p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/ruta/hacia/elproyecto')), '/ruta/hacia/');

// añade un nuevo fichero utilizando la API de acceso por array
$p['fichero1.txt'] = 'Información';
$fp = fopen('grosfichero.dat', 'rb');
// copia todos los datos del flujo
$p['data/grosfichero.dat'] = $fp;

if (
Phar::canCompress(Phar::GZ)) {
$p['data/grosfichero.dat']->compress(Phar::GZ);
}

$p['images/wow.jpg'] = file_get_contents('images/wow.jpg');
// cualquier valor puede ser guardado como metadatos específicos del fichero
$p['images/wow.jpg']->setMetadata(array('mime-type' => 'image/jpeg'));
$p['index.php'] = file_get_contents('index.php');
$p->setMetadata(array('bootstrap' => 'index.php'));

// guarda el archivo phar en el disco
$p->stopBuffering();
}
} catch (
Exception $e) {
echo
'No ha podido abrir el Phar: ', $e;
}
?>

Por otro lado, la verificación del contenido del archivo phar puede realizarse utilizando uno de los algoritmos de firma simétrica (MD5, SHA1, SHA256 y SHA512 si ext/hash está activada) y utilizando la firma asimétrica por clave pública/privada de OpenSSL. Para aprovechar la firma OpenSSL, debe generarse un par de claves pública/privada y utilizar la clave privada para firmar con Phar::setSignatureAlgorithm(). Además, la clave pública, extraída utilizando este código:

<?php
$public
= openssl_get_publickey(file_get_contents('private.pem'));
$pkey = '';
openssl_pkey_export($public, $pkey);
?>
debe ser guardada por separado del archivo phar que verifica. Si el archivo phar es guardado como /ruta/hacia/mon.phar, la clave pública debe ser guardada como /ruta/hacia/mon.phar.pubkey, de lo contrario phar no será capaz de verificar la firma OpenSSL.

La clase Phar también proporciona tres métodos estáticos, Phar::webPhar(), Phar::mungServer() y Phar::interceptFileFuncs() que son cruciales para empaquetar aplicaciones PHP destinadas a ser utilizadas en un sistema de ficheros clásico o como aplicación web. Phar::webPhar() implementa un controlador que enruta las llamadas HTTP al lugar correcto del archivo phar. Phar::mungServer() se utiliza para modificar los valores del array $_SERVER para indicar a las aplicaciones que utilicen estos valores. Phar::interceptFileFuncs() indica a Phar que intercepte las llamadas a fopen(), file_get_contents(), opendir(), y a todas las funciones basadas en stat (file_exists(), is_readable(), etc) y enruta todos los caminos relativos a los lugares correctos del archivo phar.

Por ejemplo, empaquetar una versión de la famosa aplicación phpMyAdmin en un archivo phar requiere simplemente este script y, a partir de entonces, phpMyAdmin.phar.tar.php puede ser accedido como un fichero clásico desde su servidor web, después de haber modificado la pareja usuario/contraseña:

<?php
@unlink('phpMyAdmin.phar.tar.php');
copy('phpMyAdmin-2.11.3-english.tar.gz', 'phpMyAdmin.phar.tar.php');
$a = new Phar('phpMyAdmin.phar.tar.php');
$a->startBuffering();
$a["phpMyAdmin-2.11.3-english/config.inc.php"] = '<?php
/* Servers configuration */
$i = 0;

/* Server localhost (config:root) [1] */
$i++;
$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';
$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';
$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';
$cfg[\'Servers\'][$i][\'compress\'] = false;
$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';
$cfg[\'Servers\'][$i][\'user\'] = \'root\';
$cfg[\'Servers\'][$i][\'password\'] = \'\';

/* End of servers configuration */
if (strpos(PHP_OS, \'WIN\') !== false) {
$cfg[\'UploadDir\'] = getcwd();
} else {
$cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';
@mkdir(\'/tmp/pharphpmyadmin\');
@chmod(\'/tmp/pharphpmyadmin\', 0777);
}'
;
$a->setStub('<?php
Phar::interceptFileFuncs();
Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");
echo "phpMyAdmin está destinado a ser ejecutado desde un navegador web\n";
exit -1;
__HALT_COMPILER();
'
);
$a->stopBuffering();
?>

add a note

User Contributed Notes 3 notes

up
15
shaun at shaunfreeman dot co dot uk
14 years ago
If you are trying to use Phar for a web application and just getting a blank screen, if you have enabled suhosin as well you have to add:

suhosin.executor.include.whitelist="phar"

to "/etc/php5/conf.d/suhosin.ini" file or your "php.ini" file.

once done everything works fine and dandy.
up
9
ch1902
11 years ago
If you are going to be running a webPhar from the browser, for example http://localhost/myphar.phar then you will probably have to associate the .phar extension with PHP in your webserver to interpret the PHP code. In Apache modify httpd.conf to include

AddType application/x-httpd-php .php .phar
up
3
frame86 at live dot com
12 years ago
The openssl example is completely wrong. The public key must be extracted from certificate and openssl_pkey_export() is for private key only.

Working example:
<?php
$publicKey
= openssl_get_publickey(file_get_contents('certificate.pem'));
$details = openssl_pkey_get_details($publicKey);
file_put_contents('my.phar.pubkey', $details['key']);
?>

No need to say that the best and strongest encryption of my.phar/.phar/signature.bin is useless if the consumer does not check against a valid fingerprint or certificate of public key as anybody can open, read, recreate and sign a new archive with new key. Do you do? Think about it.
To Top