I have a problem with a script with a command line.. The PHP script never continue..
Have tried to call the command line directly through putty and it outputs alot of errors but returns/completes instantly. Why doesn't it then return back to PHP?
It works fine with other PDF files, but not this one
pdf
http://docdro.id/b0M5vfw
code
$Cmd = new Command;
if($err = $Cmd->exec('/var/bin/poppler-0.51.0/utils/pdfimages -list /var/test.pdf')){
echo "ERR: $err\n";
}
echo "continue\n";
class
class Command {
private $descriptorspec;
private $output = '';
private $process;
private $pipes = [];
public function __construct(){
$this->descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'] // stderr
];
}
public function output(): string{
return $this->output;
}
public function close(){
foreach($this->pipes as $pipe){
if(is_resource($pipe)){
fclose($pipe);
}
}
proc_close($this->process);
}
public function exec(string $syntax){
$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);
$this->output = stream_get_contents($this->pipes[1]);
$stderr = stream_get_contents($this->pipes[2]);
$this->close();
return $stderr;
}
}
error
# /var/bin/poppler-0.51.0/utils/pdfimages -list /var/test.pdf
page num type width height color comp bpc enc interp object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
1 0 image 2154 303 rgb 3 8 jpeg yes [inline] 289 292 - -
Syntax Error (50560): Illegal character '>'
Syntax Error (50560): Unknown operator '<10><07><82>;w<ad><a2><b4>2r<1f><10><07><8f>~j<c4>Hq<cf>Z<86>'
Syntax Error (50568): Unknown operator '<0f><b5>X<8f><ae><d0>:<d7>DU<91><cb>'v'
Syntax Error (50568): Illegal character ')'
........
Syntax Error (66698): Illegal character <04> in hex string
Syntax Error (66699): Illegal character <ff> in hex string
Syntax Error (66699): Illegal character <c1> in hex string
Syntax Error (66705): Unknown operator '<9b>'
Syntax Error (66714): Illegal character ')'
Syntax Error (66714): Unknown operator '<bc>q<ff>'
Syntax Error (66720): Unknown operator '<05>6<f8><c2><fa><d7><c3>?<f8>'
Syntax Error (66741): Unknown operator '<df><ec><99><e1>-'
Syntax Error (66743): Unknown operator ']'
Syntax Error (66762): Unknown operator '<cc>'
Syntax Error: Unterminated string
Syntax Error: End of file inside array
Syntax Error: End of file inside array
Syntax Error: Leftover args in content stream
The PDF is problematic - #dwarring already eluded to this in the comments (quoted here to credit the commenter)
#dwarring said "just quickly, I'm pretty sure that this PDF is dying because the content stream contains an inline image started by and 'BI' followed by random data and ended by 'EI'. The Adobe engineers were having an off-day when they designed these operators, the problem being that situations arise where the binary data randomly contains 'EI' and makes the PDF unparsable. Some tools may handle this better, but ideally the producer of this image should avoid the use of inline images."
From the PHP side of things, though, instead of an if statement use a try/catch block and you should retain control of the script.
$Cmd = new Command;
try {
$err = $Cmd->exec('/var/bin/poppler-0.51.0/utils/pdfimages - list/var/test.pdf')){
} catch (Exception $e) {
var_log($e);
}
echo "continue\n";
You could use stream_select in conjunction with feof to check which of the two read streams have data available, like the following code.
I've tested it (using PHP 7) and it does not block here (with the modifications made).
public function exec(string $syntax){
$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);
$stderr = "";
$num_changed_streams = NULL;
while (!feof($this->pipes[1]) || !feof($this->pipes[2])) {
$read = [$this->pipes[1], $this->pipes[2]];
$write = NULL;
$err = NULL;
$num_changed_streams = stream_select($read, $write, $err, 3);
if ($num_changed_streams === false) {
$this->close();
return $stderr;
} else {
if (isset($read[0])) {
$this->output .= stream_get_contents($read[0]);
echo "output: {$this->output} ";
}
if (isset($read[1])) {
$stderr .= stream_get_contents($read[1]);
echo "stderr: {$stderr}";
}
}
}
$this->close();
return $stderr;
}
The stream_select and feof functions are needed because of the following (cited from http://php.net/manual/en/function.stream-select.php):
The streams listed in the read array will be watched to see if characters become available for reading (more precisely, to see if a read will not block - in particular, a stream resource is also ready on end-of-file, in which case an fread() will return a zero length string).
The problem is that this program /var/bin/poppler-0.51.0/utils/pdfimages does not write anything to the stdout and your code hangs at $this->output = stream_get_contents($this->pipes[1]); hence your class is not good for this program. For programs that don't write anything to stdout you must not read from $this->pipes[1]. You should have another class that is used for this particular type of applications:
class CommandWithNoOutput {
private $descriptorspec;
private $process;
private $pipes = [];
private $output = '';
public function __construct(){
$this->descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'] // stderr
];
}
public function output(): string{
return (string)$this->output;
}
public function close(){
foreach($this->pipes as $pipe){
if(is_resource($pipe)){
fclose($pipe);
}
}
proc_close($this->process);
}
public function exec($syntax){
$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);
$stderr = stream_get_contents($this->pipes[2]);
$this->close();
$this->output = ob_get_clean();
return $stderr;
}
}
$Cmd = new CommandWithNoOutput;
if($err = $Cmd->exec('/usr/bin/pdfimages -list test.pdf')){
echo "ERR: $err\n";
}
echo "continue\n";
This code outputs this:
ERR: Syntax Error (50560): Illegal character '>'
Syntax Error (50560): Unknown operator '<10><07><82>;w<ad><a2><b4>2r<1f><10><07><8f>~j<c4>Hq<cf>Z<86>'
Syntax Error (50568): Unknown operator '<0f><b5>X<8f><ae><d0>:<d7>DU<91><cb>'v'
Syntax Error (50568): Illegal character ')'
Syntax Error (50570): Unknown operator '<15><c7>=j<c4>X<f4><e8>'
.....a lot of errors.....
Syntax Error (66762): Unknown operator '<cc>'
Syntax Error: Unterminated string
Syntax Error: End of file inside array
Syntax Error: End of file inside array
Syntax Error: Leftover args in content stream
continue
Process finished with exit code 0
UPDATE:
Another solution is to call stream_set_blocking($this->pipes[1], 0); immediately after the call to proc_open so the code will not wait for any output.
Related
I need to put a contents of 'PHP Warning' into a variable. For these purposes I got the following code (set_error_handler() in a php class):
$data = '';
set_error_handler( function() use ($this, &$data) { $data = $this->my_error_handler(); return $data; } );
//some code that throws Warning
restore_error_handler();
function my_error_handler($errno, $errstr) {
return $errstr;
}
But I get the following 500 error: Type error: Too few arguments to function my_error_handler(), 0 passed.
If I replace a callable above with a string, code works without a 500 error, but I cannot pass a variable in it and return it with a contents of warning thrown. Any ideas how to fix it? Thank you.
i am using imagecreatefromstring and currently validate for proper image file format.
So a link of:
swqkdwfibqwfwf
Wont work, because its not a valid file type. But i have just discovered this:
sibdlsibiwbifw.png
Will send without an error from my validation. I get this error for an image link that doesnt return and image:
Warning: file_get_contents(etwteet.png): failed to open stream: No such file or directory in /var/www/clients/client2/web3/web/process/addnewbuild.php on line 141
Warning: imagecreatefromstring(): Empty string or invalid image in /var/www/clients/client2/web3/web/process/addnewbuild.php on line 141
Warning: imagejpeg() expects parameter 1 to be resource, boolean given in /var/www/clients/client2/web3/web/process/addnewbuild.php on line 143
Is there a way i can catch this error so i can stop the code processing and also notify the user?
Code used to get the URL:
$imagefile = image url;
$resource = imagecreatefromstring(file_get_contents($imagefile));
Thanks. Craig.
With all implementable validations, I believe it is finally required to capture error on imagecreatefromstring.
With an error handler...
The following syntax is supported on PHP 5.3 or later.
set_error_handler(function ($no, $msg, $file, $line) {
throw new ErrorException($msg, 0, $no, $file, $line);
});
try {
$img = imagecreatefromstring(file_get_contents("..."));
} catch (Exception $e) {
echo $e->getMessage();
}
With # and error_get_last...
if (!$img = #imagecreatefromstring(file_get_contents("..."))) {
$e = error_get_last();
die($e['message']);
}
The following syntax is supported on PHP 5.4 or later.
if (!$img = #imagecreatefromstring(file_get_contents("..."))) {
die(error_get_last()['message']);
}
The code is
// Get singleton (first value from row with single value)
static function singleton($arg, $params = false) {
return pg_fetch_row(SQL($arg, $params))[0];
}
The error message is
2014-02-19 12:54:23: (mod_fastcgi.c.2701) FastCGI-stderr: PHP message: PHP Parse error: syntax error, unexpected '[' in /var/www/blockexplorer.com/htdocs/includes/sql.inc on line 69
I think there is a config that can fix it.
This depends on PHP version you are using. If you are using PHP 5.4 or above then your code will not give error otherwise you will have to store the result in a variable and use it.
Reference : PHP 5.4
Look for "Array Dereferencing" here.
Put the result of the function in a variable
static function singleton($arg, $params = false) {
$foo = pg_fetch_row(SQL($arg, $params));
return $foo[0];
}
PHP does not support anonymous arrays. Use an named array instead:
static function singleton($arg, $params = false) {
$row=pg_fetch_row(SQL($arg, $params));
return $row[0];
}
I've discovered the "Design by contract" pattern and how to implement in in PHP. I can't find a real world example of how to do this in PHP. First question is am i'm doing it in the right way? Second one is why the assert callback is not honored?
A static class Asserts for reusable assertions:
class Asserts
{
public static function absentOrNotNumeric($value)
{
return !isset($value) ? true : is_numeric($value);
}
}
Usage:
assert_options(ASSERT_ACTIVE, true);
assert_options(ASSERT_BAIL, true);
assert_options(ASSERT_WARNING, true);
assert_options(ASSERT_CALLBACK, array('UseAsserts', 'onAssertFailure'));
class UseAsserts
{
private $value;
public function __construct($value)
{
// Single quotes are needed otherwise you'll get a
// Parse error: syntax error, unexpected T_STRING
assert('Asserts::absentOrNotNumeric($value)');
$this->value = $value;
}
public static function onAssertFailure($file, $line, $message)
{
throw new Exception($message);
}
}
// This will trigger a warning and stops execution, but Exception is not thrown
$fail = new UseAsserts('Should fail.');
Only the (right) warning is triggered:
Warning: assert() [function.assert]: Assertion
"Asserts::absetOrNotNumeric($value)" failed.
Your exception is being thrown, altering it to:
public static function onAssertFailure($file, $line, $message)
{
echo "<hr>Assertion Failed:
File '$file'<br />
Line '$line'<br />
Code '$code'<br /><hr />";
}
results in a display of the text, some testing discovers that if you alter this option
assert_options(ASSERT_BAIL, false);
The exception will be thrown, so it seems that it bails on the execution prior to throwing the exception.
Hope that helps
Your code: http://codepad.org/y10BlV8m
My code: http://codepad.org/slSX3HKd
Try using double quotes: assert("Asserts::absentOrNotNumeric($value)");
I'm having a bit of trouble defining a property in a PHP class I'm creating.
<?php
class news_parser {
public $var1 = Array();
function contents($parser, $data) {
printf($data);
}
function start_tag($parser, $data, $attribs) {
printf($data);
}
function end_tag($parser, $data) {
printf($data);
}
function parse() {
if(!$file = fopen("http://services.digg.com/2.0/story.getTopNews?type=rss&topic=technology", "r"))
die("Error opening file");
$data = fread($file, 80000);
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, array($this, "start_tag"), array($this, "end_tag"));
xml_set_character_data_handler($xml_parser, array($this, "contents"));
if(!xml_parse($xml_parser, $data, feof($fh)))
die("Error on line " . xml_get_current_line_number($xml_parser));
xml_parser_free($xml_parser);
fclose($fh);
}
}
$digg_parser = new news_parser();
$digg_parser->parse();
echo phpversion();
?>
Produces the following error:
Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /homepages/8/d335242830/htdocs/caseyflynn/php/display_formatted_RSS_feed.php on line 3
As far as I can tell I have the correct syntax. My server is running PHP 4.5. Any ideas?
My server is running PHP 4.5
This is your problem: PHP 4 doesn't know the public keyword - along with a heap of other OOP features.
As #konforce says, in the code you show, you can simply switch to using the var keyword. But the best thing would really be to switch to PHP 5. PHP 4's time is really, really over.