I'm trying to get ImageMagick to count the amount of pages in a PDF file for me. The function is as follows:
<?php
function countPdfPages($filepath)
{
$magick = "identify -format %n ".$filepath;
exec($magick, $debug, $result);
return $result;
}
?>
However, that function always returns 0. I have verified that ImageMagick is running properly, so that shouldn't be a problem. Am I not using exec() properly? Should I retrieve the output in another way? I've also tried using $debug, but that didn't give me any output, oddly.
I bet I'm doing something stupid here, but I just don't see it. Can anyone give me a push in the right direction? Thanks!
As noted in the man page, exec provides the return status of the executed command via the third argument. A value of 0 means that it exited normally. It sounds like you should be using something like popen.
Here's an example lifted from Example #3 of the fread man page (edited to use popen):
<?php
// For PHP 5 and up
$handle = popen("identify -format %n myfile.jpg", "r");
$contents = stream_get_contents($handle);
pclose($handle);
// $contents is the output of the 'identify' process
?>
Related
actual I finished writing my program. Because it is only a plugin and it runs on a external server I still want to see if I get some errors or something else in the console.
I wrote every console input with echo ...;. My question now is if it is possible to get the text of the console?
Because then I could easily safe it in a .txt file and could get access to it from the web :) - Or is there another way to get the console text?
I could probably just say fwrite(...) instand of echo ...;. But this will cost a lot of time...
Greetings and Thank You!
An alternative that could be usefull on windows would be to save all the output buffer to a txt, first check your php configuration for the console app implicit_flush must be off then
<?php
ob_start(); //before any echo
/** YOUR CODE HERE **/
$output = ob_get_contents(); //this variable has all the echoes
file_put_contents('c:\whatever.txt',$output);
ob_flush(); //shows the echoes on console
?>
If your goal is to create a text file to access, then you should create a text file directly.
(do this instead of echoing to console)
$output = $consoleData . "\n";
$output .= $moreConsoleData . "\n";
(Once you've completed that, just create the file:)
$file = fopen('output.txt', 'a');
fwrite($file, $output);
fclose($file);
Of course, this is sparse - you should also check that the file exists, create it if necessary, etc.
For console (commando line interface) you can redirect the output of your script:
php yourscript.php > path-of-your-file.txt
If you haven't access to a command line interface or to edit the cronjob line, you can duplicate the starndar output at the begining of the script:
$fdout = fopen('path-to-your-script.txt', 'wb');
eio_dup2($fdout, STDOUT);
eio_event_loop();
fclose($fdout);
(eio is an pecl extension)
If you are running the script using the console (i.e. php yourscript.php), you can easily save the output my modifying your command to:
php yourscript.php > path/to/log.txt
The above command will capture all output by the script and save it to log.txt. Change the paths for your script / log as required.
I'm currently creating a php page which does a ssh call with a .rb (ruby) file.
rb file
require 'metainspector'
page = MetaInspector.new("www.hln.be")
puts page.image
When creating a php file with the following code (php):
$cmd = "ruby facescrape.rb";
$last_line = system($cmd, $retval);
echo $last_line . '
echo $retval;
this only returns value 1.
However 2 things :
When running the same command in ssh, it will print the page.image
correctly.
When i change the rb file and for instance set as last line
puts "test"
this value returns correctly with also print correctly with the aboven php code.
I don't get why printing the page.image works in ssh but won't work by using that php code.
Also tried using exec() instead of system().
Thank you in advance!
Kind regards,
Kurt Colemonts
I have the following code
function generate_pdf() {
$fdf_data_strings = $this->get_hash_for_pdf();
#$fdf_data_names = array('49a' => "yes");
$fdf_data_names = array();
$fields_hidden = array();
$fields_readonly = array();
$hud_pdf = ABSPATH.'../pdf/HUD3.pdf';
$fdf= forge_fdf( '',
$fdf_data_strings,
$fdf_data_names,
$fields_hidden,
$fields_readonly );
/* echo "<pre>";
print_r($fdf);
echo "</pre>";
die('');
*/
$fdf_fn= tempnam( '.', 'fdf' );
$fp= fopen( $fdf_fn, 'w' );
if( $fp ) {
fwrite( $fp, $fdf );
//$data=fread( $fp, $fdf );
// echo $data;
fclose( $fp );
header( 'Content-type: application/pdf' );
header( 'Content-disposition: attachment; filename=settlement.pdf' ); // prompt to save to disk
passthru( 'pdftk HUD3.pdf fill_form '. $fdf_fn.' output - flatten');
unlink( $fdf_fn ); // delete temp file
}
else { // error
echo 'Error: unable to open temp file for writing fdf data: '. $fdf_fn;
}
}
}
is there anything wrong with it?
the problem is, I have installed pdftk
runing whereis pdftk gives me '/usr/local/bin/pdftk'
physically checked the location, pdftk is there at the said location..
using terminal, if i run pdftk --version or any other command, it runs
if I use php like passthru('/usr/local/bin/pdftk --version') nothing is displayed
if I used php like system("PATH=/usr/local/bin && pdftk --version"); it says '/usr/local/bin /pdftk :there is no directory of file '
when I run this function script , prompt for file download pops, but when i save it, nothng is saved,
i have checked permission for this folder and changed it 0755, 0766, 0777, 0666 i have tried all, nothng works
For 3 days, i am striving to get over it, and I have asked question regarding this too, but Can't figure out what the hell is going on with me.
Can somebody help me before i strike my head with wall?
The pasthru function does not execute the program through the shell.
Pass the exact path into the passthru command.
E.g.
passthru( '/usr/local/bin/pdftk HUD3.pdf fill_form '. $fdf_fn.' output - flatten');
or
passthru( '/usr/local/bin/pdftk' . $hud_pdf . 'fill_form '. $fdf_fn.' output - flatten');
If this still doesn't work test using
<?php passthru("/path/to/pdftk --help"); ?> where /path/to/pdftk is your path returned by which or where is, to ensure path is correct.
If path is correct then the issue may be related to permissions either on the temporary directory you tell pdftk to use or the permissions on the pdftk binary with regards to the apache user.
If these permissions are fine you can verify the pdftk starts up from php but hangs from running your command, then might be able to try the workaround listed here.
Further documentation on passthru is avaliable passthru PHP Manual.
As a side note, the putenv php function is used to set environment variables.
E.g. putenv('PATH='.getenv('PATH').':.');
All 3 PHP functions: exec(), system() and passthru() executes an external command, but the differences are:
exec(): returns the last line of output from the command and flushes nothing.
shell_exec(): returns the entire output from the command and flushes nothing.
system(): returns the last line of output from the command and tries to flush the output buffer after each line of the output as it goes.
passthru(): returns nothing and passes the resulting output without interference to the browser, especially useful when the output is in binary format.
Also see PHP exec vs-system vs passthru SO Question.
The implementation of these functions is located at exec.c and uses popen.
I had the same issue and this is working after lots of experiments :
function InvokePDFtk($pdf_tpl, $xfdf,$output){
$params=" $pdf_tpl fill_form $xfdf output $output flatten 2>&1";
$pdftk_path=exec('/usr/bin/which /usr/local/bin/pdftk');
$have_pdftk= $pdftk_path=='/usr/local/bin/pdftk' ;
$pdftk_path=$have_pdftk ? $pdftk_path : 'pdftk ';
exec($pdftk_path.$params,$return_var);
return array('status'=> $have_pdftk,
'command' =>$pdftk_path.$params, 'output'=>$return_var);
}
hope this might give you some insight . (change according to your needs)
Completing Appleman answer, those 3 functions can be considered as dangerous, because they allow you execute program using php, thus an attacker that exploited one of your script if you are not careful enougth. So in many php configuration that want to be safe they are disabled.
So you should check for the disable_functions directive in you php.ini(and any php configuration file) and see if the function you use is disabled.
Perhaps you should keep fclose out of the if statement, make sure you have it directed to the right file! :)
Is your web server chrooted? Try putting the executable into a directory that is viewable by the server.
Play around around with safe mode and definitely check your web server log file, normally in:
/var/log/apache2/error.log
The code below almost works, but it's not what I really meant:
ob_start();
echo 'xxx';
$contents = ob_get_contents();
ob_end_clean();
file_put_contents($file,$contents);
Is there a more natural way?
It is possible to write STDOUT directly to a file in PHP, which is much easier and more straightforward than using output bufferering.
Do this in the very beginning of your script:
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('application.log', 'wb');
$STDERR = fopen('error.log', 'wb');
Why at the very beginning you may ask? No file descriptors should be opened yet, because when you close the standard input, output and error file descriptors, the first three new descriptors will become the NEW standard input, output and error file descriptors.
In my example here I redirected standard input to /dev/null and the output and error file descriptors to log files. This is common practice when making a daemon script in PHP.
To write to the application.log file, this would suffice:
echo "Hello world\n";
To write to the error.log, one would have to do:
fwrite($STDERR, "Something went wrong\n");
Please note that when you change the input, output and error descriptors, the build-in PHP constants STDIN, STDOUT and STDERR will be rendered unusable. PHP will not update these constants to the new descriptors and it is not allowed to redefine these constants (they are called constants for a reason after all).
here's a way to divert OUTPUT which appears to be the original problem
$ob_file = fopen('test.txt','w');
function ob_file_callback($buffer)
{
global $ob_file;
fwrite($ob_file,$buffer);
}
ob_start('ob_file_callback');
more info here:
http://my.opera.com/zomg/blog/2007/10/03/how-to-easily-redirect-php-output-to-a-file
None of the answers worked for my particular case where I needed a cross platform way of redirecting the output as soon as it was echo'd out so that I could follow the logs with tail -f log.txt or another log viewing app.
I came up with the following solution:
$logFp = fopen('log.txt', 'w');
ob_start(function($buffer) use($logFp){
fwrite($logFp, $buffer);
}, 1); //notice the use of chunk_size == 1
echo "first output\n";
sleep(10)
echo "second output\n";
ob_end_clean();
I haven't noticed any performance issues but if you do, you can change chunk_size to greater values.
Now just tail -f the log file:
tail -f log.txt
No, output buffering is as good as it gets. Though it's slightly nicer to just do
ob_start();
echo 'xxx';
$contents = ob_get_flush();
file_put_contents($file,$contents);
Using eio pecl module eio is very easy, also you can capture PHP internal errors, var_dump, echo, etc. In this code, you can found some examples of different situations.
$fdout = fopen('/tmp/stdout.log', 'wb');
$fderr = fopen('/tmp/stderr.log', 'wb');
eio_dup2($fdout, STDOUT);
eio_dup2($fderr, STDERR);
eio_event_loop();
fclose($fdout);
fclose($fderr);
// output examples
echo "message to stdout\n";
$v2dump = array(10, "graphinux");
var_dump($v2dump);
// php internal error/warning
$div0 = 10/0;
// user errors messages
fwrite(STDERR, "user controlled error\n");
Call to eio_event_loop is used to be sure that previous eio requests have been processed. If you need append on log, on fopen call, use mode 'ab' instead of 'wb'.
Install eio module is very easy (http://php.net/manual/es/eio.installation.php). I tested this example with version 1.2.6 of eio module.
You can install Eio extension
pecl install eio
and duplicate a file descriptor
$temp=fopen('/tmp/my_stdout','a');
$my_data='my something';
$foo=eio_dup2($temp,STDOUT,EIO_PRI_MAX,function($data,$esult,$request){
var_dump($data,$esult,$request);
var_dump(eio_get_last_error($request));
},$my_data);
eio_event_loop();
echo "something to stdout\n";
fclose($temp);
this creates new file descriptor and rewrites target stream of STDOUT
this can be done with STDERR as well
and constants STD[OUT|ERR] are still usable
I understand that this question is ancient, but people trying to do what this question asks will likely end up here... Both of you.
If you are running under a particular environment...
Running under Linux (probably most other Unix like operating systems, untested)
Running via CLI (Untested on web servers)
You can actually close all of your file descriptors (yes all, which means it's probably best to do this at the very beginning of execution... for example just after a pcntl_fork() call to background the process in a daemon (which seems like the most common need for something like this)
fclose( STDIN ); // fd 3
fclose( STDERR); // fd 2
fclose( STDOUT ); // fd 1
And then re-open the file descriptors, assigning them to a variable that will not fall out of scope and thus be garbage collected. Because Linux will predictably open them in the proper order.
$kept_in_scope_variable_fd1 = fopen(...); // fd 1
$kept_in_scope_variable_fd2 = fopen(...); // fd 2
$kept_in_scope_variable_fd3 = fopen( '/dev/null', ... ); // fd 3
You can use whatever files or devices you want for this. I gave /dev/null as the example for STDIN (fd3) because that's probably the most common case for this kind of code.
Once this is done you should be able to do normal things like echo, print_r, var_dump, etc without specifically needing to write to a file with a function. Which is useful when you're trying to background code that you do not want to, or aren't able to, rewrite to be file-pointer-output-friendly.
YMMV for other environments and things like having other FD's open, etc. My advice is to start with a small test script to prove that it works, or doesn't, in your environment and then move on to integration from there.
Good luck.
Here is an ugly solution that was useful for a problem I had (need to debug).
if(file_get_contents("out.txt") != "in progress")
{
file_put_contents("out.txt","in progress");
$content = file_get_contents('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
file_put_contents("out.txt",$content);
}
The main drawback of that is that you'd better not to use the $_POST variables.
But you dont have to put it in the very beggining.
So, I'm looking for something more efficient than this:
<?php
ob_start();
include 'test.php';
$content = ob_get_contents();
file_put_contents('test.html', $content);
echo $content;
?>
The problems with the above:
Client doesn't receive anything until the entire page is rendered
File might be enormous, so I'd rather not have the whole thing in memory
Any suggestions?
Interesting problem; don't think I've tried to solve this before.
I'm thinking you'll need to have a second request going from your front-facing PHP script to your server. This could be a simple call to http://localhost/test.php. If you use fopen-wrappers, you could use fread() to pull the output of test.php as it is rendered, and after each chunk is received, output it to the screen and append it to your test.html file.
Here's how that might look (untested!):
<?php
$remote_fp = fopen("http://localhost/test.php", "r");
$local_fp = fopen("test.html", "w");
while ($buf = fread($remote_fp, 1024)) {
echo $buf;
fwrite($local_fp, $buf);
}
fclose($remote_fp);
fclose($local_fp);
?>
A better way to do this is to use the first two parameters accepted by ob_start: output_callback and chunk_size. The former specifies a callback to handle output as it's buffered, and the latter specifies the size of the chunks of output to handle.
Here's an example:
$output_file = fopen('test.html', 'w');
if ($output_file === false) {
// Handle error
}
$write_ob_to_file = function($buffer) use ($output_file) {
fwrite($output_file, $buffer);
// Output string as-is
return false;
};
ob_start($write_ob_to_file, 4096);
include 'test.php';
ob_end_flush();
fclose($output_file);
In this example, the output buffer will be flushed (sent) for every 4096 bytes of output (and once more at the end by the ob_end_flush call). Each time the buffer is flushed, the callback $write_ob_to_file will be called and passed the latest chunk. This gets written to test.html. The callback then returns false, meaning "output this chunk as is". If you wanted to only write the output to file and not to PHP's output stream, you could return an empty string instead.
Pix0r's answer is what you want unless you actually need it "included" rather than just executed. For example, if you have login information before the test.php, it will not get passed into the file if you call it with fopen.
If you need it genuinely included, then what you have is the simplest method, but if you want constant output, you'll need to actually write test.php in a manner that outputs as well as stores the information as it goes. As far as I know there's no way to both collect buffer and output it as you go.
Here you go x-send-file, use mod_xsendfile to send file efficiently, really easy.