How to place a phar file inside a phar file?

有些话、适合烂在心里 提交于 2020-01-12 04:31:34

问题


I'd like to place a phar file inside a phar file. I tried it most straight forward:

$p = new Phar('test.phar', null, 'self.phar');
$p->setStub('<?php Phar::mapPhar();
include \'phar://self.phar/index.php\'; __HALT_COMPILER(); ?>');
$p['index.php'] = '<?php
echo "hello world\n";';

$p = new Phar('test2.phar', null, 'self.phar');
$p->setStub('<?php Phar::mapPhar();
include \'phar://self.phar/index.php\'; __HALT_COMPILER(); ?>');
$p['index.php'] = '<?php
echo "hello phar world\n";';
$p['test.phar'] = file_get_contents('test.phar');

However PHP just does not want to open it. It does not accept any of the following includes:

// Warning: Phar::mapPhar(phar://path/to/test2.phar/test.phar): failed to open
// stream: Invalid argument in phar://path/to/test2.phar/test.phar
include('phar://test2.phar/test.phar');

// Warning: include(phar://test2.phar/test.phar/index.php): failed to open
// stream: phar error: "test.phar/index.php" is not a file in phar "test2.phar"
include('phar://test2.phar/test.phar/index.php');

// Warning: include(phar://test2.phar/phar://test.phar/index.php): failed to
// open stream: phar error: "phar:/test.phar/index.php" is not a file in phar
// "test2.phar"
include('phar://test2.phar/phar://test.phar/index.php');

I know the constructiveness of this question is limited, because it might just not work with phar-in-phar however probably I've just been missing a way how to do that and I'm just not seeing the wood for the trees.


回答1:


The function that you should use to load a phar file in PHP is Phar::loadPhar e.g.

Phar::loadPhar("test2.phar", "test2");

Would make the phar file test2.phar be loaded and accessible via the alias test2, so you could include files from it by doing:

include ('phar://test2/index.php');

However it appears that this does not work if that file is inside a phar itself. The PHP code for loadPhar is:

fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);

and apparently the IGNORE_URL flag makes it impossible for the file to be opened.

There is a workaround - extract the phar file that is contained inside the other phar to a temporary file, and then it apparently can be loaded without any issue. The following code will extract a phar file (phar1.phar) that is contained in a 2nd phar file, and then call loadPhar.

function extractAndLoadPhar(){

    $tempFilename =  tempnam( sys_get_temp_dir() , "phar");

    $readHandle = fopen("phar://phar2/phar1.phar", "r");
    $writeHandle =  fopen($tempFilename, "w");

    while (!feof($readHandle)) {
        $result = fread($readHandle, 512);
        fwrite($writeHandle, $result);
    }

    fclose($readHandle);
    fclose($writeHandle);

    $result = Phar::loadPhar($tempFilename, "phar1");
}

extractAndLoadPhar(); //Extract and load the phar
include ('phar://phar1/src1.php'); //It can now be referenced by 'phar1'

I have placed a working copy of this code here https://github.com/Danack/pharphar which creates a phar, embeds it in a 2nd phar, and then loads and calls a function from the 1st phar inside the 2nd phar.

To note - I'm not convinced that this technique is a good idea. There seems to be some ambiguity (aka I didn't understand) what happens to the stub files for each of the phar files. i.e. do they both get loaded, or is it just the outermost phar file that has it's stub loaded and run.



来源:https://stackoverflow.com/questions/13180438/how-to-place-a-phar-file-inside-a-phar-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!