📜 ⬆️ ⬇️

We do self-extracting archive or sections in PHP files

Only one thing prompted me to write this code - the dumb FTP of some hosters.
No, the files are uploaded with the maximum speed, but 30 seconds pass between the end of downloading one file and the start of downloading the next.
Since I now suffer from the crap I make up and put Jomly in shock quantities, loading 5000+ files leads to reading the Habra and Google-rider to holes, which, however, is also harmful to health.
In order to correct this annoying omission, a small knee-length creak is being written.



A script is known as such a thing that it can be launched not only on the server, but also from the console, which means that it is necessary to provide for the operation of both options.
Isset is used to define the console ($ argv)
Actually the code of packing and unpacking is not interesting.
But what I would like to draw the attention of% username% is how exactly the packer is organized.
To do this, I am talking about one function and one constant about which not only schoolchildren and Indians do not know.
')
This is the function __compiler_halt and the constant __COMPILER_HALT_OFFSET__ , both entered in PHP since 5.1
When parsing a file if php stumbles upon __compiler_halt (); then it completes the parsing and sets in __COMPILER_HALT_OFFSET__ the byte number of the next to the semicolon after the function name
It is important to understand that no?> Is no longer required after this construction
What does this give us?
And it gives us the opportunity to store arbitrary data of any kind in our php code
And this data is read very easily: file_get_contents (__ FILE __, null, null, __ COMPILER_HALT_OFFSET__);
If this file is used it is split into 2 sections - the code section and the data section

The packer contains the packing code in the code section, and the unpacking code in the data section
The unpacker contains a loved one in the code section, and a zip archive with data in the data section.

Without further annoyance, I quote the code:

<?php

$packname
= getcwd (). '/' . basename ( __FILE__ , '.php' ). '.packed.php' ;
$zip = new ZipArchive ();
$zip -> open ( $packname , ZIPARCHIVE :: CREATE | ZIPARCHIVE :: OVERWRITE );
$iterator = new RecursiveIteratorIterator (new RecursiveDirectoryIterator ( './' ));
$packer = realpath ( __FILE__ );
foreach(
$iterator as $key => $value )
{
$file = realpath ( $key );
if(
$file != $packer )
$zip -> addFile ( $file , $key );
}
$zip -> close ();

$data = file_get_contents ( __FILE__ , null , null , __COMPILER_HALT_OFFSET__ );
$zipped = @ file_get_contents ( $packname );
if(
$zipped == '' ) die();
file_put_contents ( $packname , $data . $zipped );

__halt_compiler();<?
php
$mode
= '' ;
if(isset(
$argv [ 1 ]))
{
$mode = $argv [ 1 ];
}
if(isset(
$_REQUEST [ 'mode' ]))
{
$mode = $_REQUEST [ 'mode' ];
}
function
extract_archive ()
{
file_put_contents ( getcwd (). '/' . basename ( __FILE__ ). '.zip' , file_get_contents ( __FILE__ , null , null , __COMPILER_HALT_OFFSET__ ));
}
$file = basename ( __FILE__ );
if(!isset(
$argv ))
echo <<<HEREDOC
<html>
<head>
<title> $file</title>
</head>
<body style="font-size:24px;">
HEREDOC;
switch(
$mode )
{
case
'extract' :
extract_archive ();
echo
"\n" ;
break;
case
'unpack' :
extract_archive ();
$zip = new ZipArchive ;
$zip -> open ( getcwd (). '/' . basename ( __FILE__ ). '.zip' );
$zip -> extractTo ( './' );
$zip -> close ();
unlink ( getcwd (). '/' . basename ( __FILE__ ). '.zip' );
unlink ( __FILE__ );
echo
"\n" ;
break;
default:

if(isset(
$argv ))
{
echo <<<HEREDOC
Extract me with
php $file extract
Unpack me with
php $file unpack

HEREDOC;
}
else
{
echo
'<a href="?mode=unpack"> </a><br><a href="?mode=extract"> </a>' ;
}
}
if(!isset(
$argv )) echo '</body></html>' ;
__halt_compiler();




Well, for today this is all I wanted to say, unless breaking the tradition I will ask to kick my feet for the shoals in the first post on the habr, otherwise it will be too late :)

Source: https://habr.com/ru/post/84197/


All Articles