I'm trying to use 1 include file for both perl and php
Is there a nice way to import a myphp.inc file within perl?
$ cat myphp.inc
<?php
$some_var="hello world";
?>
Using the above in my test.php works fine:
include "myphp.inc";
If I remove the < ? php then test.php will just print out the contents of the myphp.inc file... if I leave them in then my perl programs complains with:
Unterminated <> operator
I've seen the perl module: PHP::Include but I would like to stay away from external modules if possible.
Anyone have ideas on doing this??
Don't try to write code that is both PHP and Perl, they are different languages, even if they have some shared ancestry. If you want to share data between the two, then use a structured data format. JSON is a popular flavour. PHP has parse_json and Perl has the JSON module.
I would like to stay away from external modules if possible
Code reuse is a virtue … although there is nothing stopping you reimplementing the modules from scratch.
Ideally you would store the shared/configuration data in a format easily readable in both PHP and Perl. XML, JSON, or a simple text file with key-value pairs (as in the .ini file that simbabque suggests) would work great.
If you are determined to read the PHP file in Perl but you do not want to use a module such as PHP::Include then you are left with writing something like this:
use IO::File;
sub require_php {
my $source_filename = $_[0];
my $dest_filename = 'temp.inc.pl';
open my $source, $source_filename or die "Could not open $source_filename: $!";
open my $destination, '>>'.$dest_filename or die "Cound not open file for writing";
while(my $line = <$source>) {
if(index($line,'<?php')==-1 && index($line,'?>')==-1) {
print $destination $line
}
}
close $destination;
close $source;
require $dest_filename;
unlink $dest_filename;
}
our $some_var = '';
require_php('myphp.inc');
which will end with $some_var having the value of "hello world".
Related
For debugging purposes, when working on PHP projects with many file / many include (example: Wordpress code), I would sometimes be interested in seeing the "unwrapped" code, and to amalgamate / flatten ("flatten" is the terminology used in Photoshop-like tools when you merge many layers into one layer) all files into one big PHP file.
How to do an amalgamation of multiple PHP files?
Example:
$ php index.php --amalgamation
would take these files as input:
vars.php
<?php
$color = 'green';
$fruit = 'apple';
?>
index.php
<?php
include 'vars.php';
echo "A $color $fruit";
?>
and produce this amalgamated output:
<?php
$color = 'green';
$fruit = 'apple';
echo "A $color $fruit";
?>
(it should work also with many files, e.g. if index.php includes vars.php which itself includes abc.php).
We can write an amalgamation/bundling script that fetches a given file's contents and matches any instances of include|require, and then fetches any referred files' contents, and substitutes the include/require calls with the actual code.
The following is a rudimentary implementation that will work (based on a very limited test on files with nested references) with any number of files that include/require other files.
<?php
// Main file that references further files:
$start = 'test/test.php';
function bundle_files(string $filepath)
{
// Fetch current code
$code = file_get_contents($filepath);
// Set directory for referred files
$dirname = pathinfo($filepath, PATHINFO_DIRNAME);
// Match and substitute include/require(_once) with code:
$rx = '~((include|require)(_once)?)\s+[\'"](?<path>[^\'"]+)[\'"];~';
$code = preg_replace_callback($rx, function($m) use ($dirname) {
// Ensure a valid filepath or abort:
if($path = realpath($dirname . '/' . $m['path'])) {
return bundle_files($path);
} else {
die("Filepath Read Fail: {$dirname}/{$m['path']}");
}
}, $code);
// Remove opening PHP tags, note source filepath
$code = preg_replace('~^\s*<\?php\s*~i', "\n// ==== Source: {$filepath} ====\n\n", $code);
// Remove closing PHP tags, if any
$code = preg_replace('~\?>\s*$~', '', $code);
return $code;
}
$bundle = '<?php ' . "\n" . bundle_files($start);
file_put_contents('bundle.php', $bundle);
echo $bundle;
Here we use preg_replace_callback() to match and substitute in order of appearance, with the callback calling the bundling function on each matched filepath and substituting include/require references with the actual code. The function also includes a comment line indicating the source of the included file, which may come in handy if/when you're debugging the compiled bundle file.
Notes/Homework:
You may need to refine the base directory reference routine. (Expect trouble with "incomplete" filepaths that rely on PHP include_path.)
There is no control of _once, code will be re-included. (Easy to remedy by recording included filepaths and skipping recurrences.)
Matching is only made on "path/file.php", ie. unbroken strings inside single/double quotes. Concatenated strings are not matched.
Paths including variables or constants are not understood. Files would have to be evaluated, without side-effects!, for that to be possible.
If you use declare(strict_types=1);, place it atop and eliminate following instances.
There may be other side-effects from the bundling of files that are not addressed here.
The regex does no lookbehind/around to see if your include/require is commented out!
If your code jumps in and out of PHP mode and blurts out HTML, all bets are off
Managing the inclusion of autoloaded classes is beyond this snippet.
Please report any glitches and edge cases. Feel free to develop and (freely) share.
So I have this site where I want to create a listing of best torrent Magnet URI alternatives.I'd rather list everything from some .html file:
torrent1:name_of_torrent
torrent2:name_of-torrent
...
and have PHP check for the $_POST['search_torrent'] and search that data inside the .html, if any of the specific data/name was found in any of those lines, then output that entire line as a item using foreach().
I did something like this, but the host I'm trying to accomplish this on doesn't allow exec() nor shell_exec().
<?php
if (isset($_POST['search_torrent'])) {
$search_torrent = $_POST['search_torrent'];
$torrent_file = "read.txt";
echo nl2br(shell_exec("type ".$torrent_file."| find /I \"".$search_torrent."\""));
?>
I know I know... I could use database but I'm just not into that at this moment.
Thanks!
Read the file lines into an array and grep that:
foreach(preg_grep('/'.preg_quote($_POST['search_torrent'], '/').'/i', file('read.txt')) as $line) {
echo "$line<br>";
}
I'm trying to create a simple one page php website that does the following.
Displays data from a txt file and then converts it into links.
(A line from the text file would be so if the line is "TextEdit: 1.9" ApplicationName = TextEdit)
So basically I need to add the url strings together with the application names in the desired locations and then redirect to that page. Hopefully ending up with something like:
Link[urlportion+appname+urlportion]
I am getting my data from a txt file that is formatted in the format of:
TextEdit: 1.9
AppleScript Editor: 2.6
Arduino: 1.0.5
TextWrangler: 4.5.3
etc.
I can display the code in my page using:
<?php
foreach(glob("log.txt") as $filename) {
$file = $filename;
$contents = file($file);
$string = implode("<br>",$contents);
echo $string;
echo "<br></br>";
}
?>
That works beautifully my question is how do I separate the txt file into pieces so I can concatenate it with my url and display it.
If it's simple you can just use a text file and delimit your strings. You're going to need a server-side technology to do this - PHP, ASP.NET, etc. You haven't posted what your server-side technology is, but this can't be done without it.
i want php code to open a file and search in it for some dangerous words like
if(preg_match("/(echo|zend|print|print_r|phpinfo|
symlink|ini_set|telnet|cgi|
eval|base64_encode|base64_decode)/iU",$filesource)){
echo 'error';
}
how i can make it
If you want to parse PHP code, use token_get_all to get an array of language tokens.
pretty much like you outlined :)
But have you looked at tools like phpcs and phpcpd?
You can open up any php file like a regular text file and parse through it without including it in your script.
<?php
$filedata = file_get_contents('/path/to/file.php');
if (preg_match('/foo/', $filedata) {
echo "file contained 'foo'\n";
}
I would need a tool, if it exists or if you can write in under 5 mins (don't want to waste anyone's time).
The tool in question would resolve the includes, requires, include_once and require_once in a PHP script and actually harcode the contents of then, recursively.
This would be needed to ship PHP scripts in one big file that actually use code and resources from multiple included files.
I know that PHP is not the best tool for CLI scripts, but as I'm the most pro-efficient at it, I use it to write some personal or semi-personal tools. I don't want un-helpful answers or comments that tell me to use something else than PHP or learn something else.
The idea of that approach is to be able to have a single file that would represent everything needed to put it in my personal ~/.bin/ directory and let it live there as a completely functional and self-contained script. I know I could set include paths in the script to something that would honor the XDG data directories standards or anything else, but I wanted to try that approach.
Anyway, I ask there because I don't want to re-invent the wheel and all my searches gave nothing, but if I don't have any insight here, I will continue in the way I was going to and actually write a tool that will resolve the includes and requires.
Thanks for any help!
P.S.: I forgot to include examples and don't want to rephrase the message:
Those two files
mainfile.php
<?php
include('resource.php');
include_once('resource.php');
echo returnBeef();
?>
resource.php
<?php
function returnBeef() {
return "The beef!";
}
?>
Would be "compiled" as (comments added for clarity)
<?php
/* begin of include('resource.php'); */?><?php
function returnBeef() {
return "The beef!";
}
?><?php /* end of include('resource.php); */
/*
NOT INCLUDED BECAUSE resource.php WAS PREVIOUSLY INCLUDED
include_once('resource.php');
*/
echo returnBeef();
?>
The script does not have to output explicit comments, but it could be nice if it did.
Thanks again for any help!
EDIT 1
I made a simple modification to the script. As I have begun writing the tool myself, I have seen a mistake I made in the original script. The included file would have, to do the least amount of work, to be enclosed out of start and end tags (<?php ?>)
The resulting script example has been modified in consequence, but it has not been tested.
EDIT 2
The script does not actually need to do heavy-duty parsing of the PHP script as in run-time accurate parsing. Simple includes only have to be treated (like include('file.php');).
I started working on my script and am reading the file to unintelligently parse them to include only when in <?php ?> tags, not in comments nor in strings. A small goal is to also be able to detect dirname(__FILE__)."" in an include directive and actually honor it.
An interesting problem, but one that's not really solvable without detailed runtime knowledge. Conditional includes would be nearly impossible to determine, but if you make enough simple assumptions, perhaps something like this will suffice:
<?php
# import.php
#
# Usage:
# php import.php basefile.php
if (!isset($argv[1])) die("Invalid usage.\n");
$included_files = array();
echo import_file($argv[1])."\n";
function import_file($filename)
{
global $included_files;
# this could fail because the file doesn't exist, or
# if the include path contains a run time variable
# like include($foo);
$file = #file_get_contents($filename);
if ($file === false) die("Error: Unable to open $filename\n");
# trimming whitespace so that the str_replace() at the end of
# this routine works. however, this could cause minor problems if
# the whitespace is considered significant
$file = trim($file);
# look for require/include statements. Note that this looks
# everywhere, including non-PHP portions and comments!
if (!preg_match_all('!((require|include)(_once)?)\\s*\\(?\\s*(\'|")(.+)\\4\\s*\\)?\\s*;!U', $file, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE ))
{
# nothing found, so return file contents as-is
return $file;
}
$new_file = "";
$i = 0;
foreach ($matches as $match)
{
# append the plain PHP code up to the include statement
$new_file .= substr($file, $i, $match[0][1] - $i);
# make sure to honor "include once" files
if ($match[3][0] != "_once" || !isset($included_files[$match[5][0]]))
{
# include this file
$included_files[$match[5][0]] = true;
$new_file .= ' ?>'.import_file($match[5][0]).'<?php ';
}
# update the index pointer to where the next plain chunk starts
$i = $match[0][1] + strlen($match[0][0]);
}
# append the remainder of the source PHP code
$new_file .= substr($file, $i);
return str_replace('?><?php', '', $new_file);
}
?>
There are many caveats to the above code, some of which can be worked around. (I leave that as an exercise for somebody else.) To name a few:
It doesn't honor <?php ?> blocks, so it will match inside HTML
It doesn't know about any PHP rules, so it will match inside PHP comments
It cannot handle variable includes (e.g., include $foo;)
It may introduce scope errors. (e.g., if (true) include('foo.php'); should be if (true) { include('foo.php'); }
It doesn't check for infinitely recursive includes
It doesn't know about include paths
etc...
But even in such a primitive state, it may still be useful.
You could use the built in function get_included_files which returns an array of, you guessed it, all the included files.
Here's an example, you'd drop this code at the END of mainfile.php and then run mainfile.php.
$includes = get_included_files();
$all = "";
foreach($includes as $filename) {
$all .= file_get_contents($filename);
}
file_put_contents('all.php',$all);
A few things to note:
any include which is actually not processed (ie. an include inside a function) will not be dumped into the final file. Only includes which have actually run.
This will also have a around each file but you can have multiple blocks like that with no issues inside a single text file.
This WILL include anything included within another include.
Yes, get_included_files will list the script actually running as well.
If this HAD to be a stand-alone tool instead of a drop in, you could read the inital file in, add this code in as text, then eval the entire thing (possibly dangerous).