I am using the amazon.com products API. The call is GetMatchingProductForId. When I type as single value into the call, it works. When I input a large file to my program it works, but I occasionally get a fatal error:
Fatal Error:Can Only Throw Objects in J:/filepath/client.php on line 1003.
I have no idea what the possible error is. When i contacted amazon developer support they said they would investigate the issue.
The problem could possibly be the user input because I ran my program yesterday and was able to get 2797 files in response, but eventually received the same error. When i ran my program for the first time during testing, there was no problem at all. If anyone has knowledge of this error and could explain just the error, I would greatly appreciate it.
Client.php lines 992 - 1004:
for (;;) {
$response = $this->_httpPost($parameters);
$status = $response['Status'];
if ($status == 200) {
return array('ResponseBody' => $response['ResponseBody'],
'ResponseHeaderMetadata' => $response['ResponseHeaderMetadata']);
}
if ($status == 500 && $this->_pauseOnRetry(++$retries)) {
continue;
}
throw $this->_reportAnyErrors($response['ResponseBody'],
$status, $response['ResponseHeaderMetadata']);
}
I did not edit any of this code. This came from developer.amazonservices.com
_reportAnyErrors Function :
private function _reportAnyErrors($responseBody, $status, $responseHeaderMetadata, Exception $e = null)
{
$exProps = array();
$exProps["StatusCode"] = $status;
$exProps["ResponseHeaderMetadata"] = $responseHeaderMetadata;
libxml_use_internal_errors(true); // Silence XML parsing errors
$xmlBody = simplexml_load_string($responseBody);
if ($xmlBody !== false) { // Check XML loaded without errors
$exProps["XML"] = $responseBody;
$exProps["ErrorCode"] = $xmlBody->Error->Code;
$exProps["Message"] = $xmlBody->Error->Message;
$exProps["ErrorType"] = !empty($xmlBody->Error->Type) ? $xmlBody->Error->Type : "Unknown";
$exProps["RequestId"] = !empty($xmlBody->RequestID) ? $xmlBody->RequestID : $xmlBody->RequestId; // 'd' in RequestId is sometimes capitalized
} else { // We got bad XML in response, just throw a generic exception
$exProps["Message"] = "Internal Error";
continue;
}
}
Values :
20373001862
20373002678
20373002685
20373002937
20373003002
20373003583
20373003644
20373003651
20373003675
20373003682
20373003781
20373003811
20373003828
20373003835
20373003842
20373003859
20373003866
20373003873
20373003880
20373003897
20373003903
20373005006
With these values it crashed on the third file which would be the 20th value.
Related
I get this warning in a chunk of instructions PHP 8+ dedicated to the check of the user inside the page:
if ($_POST['go'] ?? null) {
// $_SESSION_VALUES is an array $db, $nick are classes of mine
$_SESSION_VALUES = $nick->get_cookie (COOKIE_NAME); // get the name of the cookie
if ($db->check_user (USERS_TABLE, $_POST['nick'], $db->encode_password($_POST['password']))) {
$_SESSION_VALUES['_USERNAME'] = $db->user_rec['nick']; // get the nickname from the cookie
$_SESSION_VALUES['_PASSWORD'] = $db->user_rec['password']; //get the password
$_SESSION_VALUES['_USER'] = $db->user_type;
if (! $nick->set_cookie (COOKIE_NAME, $_SESSION_VALUES)) die ('Cannot write the cookie'); // record the cookie
header('Location: ./copertina'); }
else $_SESSION_VALUES['_USER'] = -1;
}
The execution of
else $_SESSION_VALUES['_USER'] = -1;
gives "Automatic conversion of false to array is deprecated"
Following a suggestion from stack overflow I tryed this:
$\_SESSION_VALUES = \[\];
if ($\_POST\['go'\] ?? null) {
...
but apparently it doesn't work
any idea?
Thanks
I assume that $nick->get_cookie(COOKIE_NAME); returns false.
Try changing:
else $_SESSION_VALUES['_USER'] = -1;
to:
else $_SESSION_VALUES = ['_USER' => -1];
This will probably get rid of the error message you reported, but I don't know if the rest of your code, which I cannot see, will accept this.
I am developing a PHP script that allows me to modify tags in an XML file and move them once done.
My script works correctly but I would like to add error handling: So that if the result of my SQL query does not return anything display an error message or better, send a mail, and not move the file with the error and move to the next.
I did some tests but the code never displays the error and it moves the file anyway.
Can someone help me to understand why? Thanks
<?php
}
}
$xml->formatOutput = true;
$xml->save($source_file);
rename($source_file,$destination_file);
}
}
closedir($dir);
?>
Give this one a try
$result = odbc_fetch_array($exec);
if ($result === false || $result['GEAN'] === null) {
echo "GEAN not found for $SKU_CODE";
// continue;
}
$barcode = (string) $result['GEAN'];
echo $barcode; echo "<br>"; //9353970875729
$node->getElementsByTagName("SKU")->item(0)->nodeValue = "";
$node->getElementsByTagName("SKU")->item(0)->appendChild($xml->createTextNode($result[GEAN]));
I'm calling through Axios a PHP script checking whether a URL passed to it as a parameter can be embedded in an iframe. That PHP script starts with opening the URL with $_GET[].
Strangely, a page with cross-origin-opener-policy: same-origin (like https://twitter.com/) can be opened with $_GET[], whereas a page with Referrer Policy: strict-origin-when-cross-origin (like https://calia.order.liven.com.au/) cannot.
I don't understand why, and it's annoying because for the pages that cannot be opened with $_GET[] I'm unable to perform my checks on them - the script just fails (meaning I get no response and the Axios call runs the catch() block).
So basically there are 3 types of pages: (1) those who allow iframe embeddability, (2) those who don't, and (3) the annoying ones who not only don't but also can't even be opened to perform this check.
Is there a way to open any page with PHP, and if not, what can I do to prevent my script from failing after several seconds?
PHP script:
$source = $_GET['url'];
$response = true;
try {
$headers = get_headers($source, 1);
$headers = array_change_key_case($headers, CASE_LOWER);
if (isset($headers['content-security-policy'])) {
$response = false;
}
else if (isset($headers['x-frame-options']) &&
$headers['x-frame-options'] == 'DENY' ||
$headers['x-frame-options'] == 'SAMEORIGIN'
) {
$response = false;
}
} catch (Exception $ex) {
$response = $ex;
}
echo $response;
EDIT: below is the console error.
Access to XMLHttpRequest at 'https://path.to.cdn/iframeHeaderChecker?url=https://calia.order.liven.com.au/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CustomLink.vue?b495:61 Error: Network Error
at createError (createError.js?2d83:16)
at XMLHttpRequest.handleError (xhr.js?b50d:84)
VM4758:1 GET https://path.to.cdn/iframeHeaderChecker?url=https://calia.order.com.au/ net::ERR_FAILED
The error you have shown is coming from Javascript, not from PHP. get_headers() returns false on failure, it will not throw an exception - the catch() never happens. get_headers() just makes an http request, like your browser, or curl, and the only reason that would fail is if the URL is malformed, or the remote site is down, etc.
It is the access from http://localhost:3000 to https://path.to.cdn/iframeHeaderChecker with Javascript that has been blocked, not PHP access to the URLs you are passing as parameters in $_GET['url'].
What you're seeing is a standard CORS error when you try to access a different domain than the one the Javascript is running on. CORS means Javascript running on one host cannot make http requests to another host, unless that other host explicitly allows it. In this case, the Javascript running at http://localhost:3000 is making an http request to a remote site https://path.to.cdn/. That's a cross-origin request (localhost !== path.to.cdn), and the server/script receiving that request on path.to.cdn is not returning any specific CORS headers allowing that request, so the request is blocked.
Note though that if the request is classed as "simple", it will actually run. So your PHP is working already, always, but bcs the right headers aren't returned, the result is blocked from being displayed in your browser. This can lead to confusion bcs for eg you might notice a delay while it gets the headers from a slow site, whereas it is super fast for a fast site. Or maybe you have logging which you see is working all the time, despite nothing showing up in your browser.
My understanding is that https://path.to.cdn/iframeHeaderChecker is your PHP script, some of the code of which you have shown in your question? If so, you have 2 choices:
Update iframeHeaderChecker to return the appropriate CORS headers, so that your cross-origin JS request is allowed. As a quick, insecure hack to allow access from anyone and anywhere (not a good idea for the long term!) you could add:
header("Access-Control-Allow-Origin: *");
But it would be better to update that to more specifically restrict access to only your app, and not everyone else. You'll have to evaluate the best way to do that depending on the specifics of your application and infrastructure. There many questions here on SO about CORS/PHP/AJAX to check for reference. You could also configure this at the web server level, rather than the application level, eg here's how to configure Apache to return those headers.
If iframeHeaderChecker is part of the same application as the Javascript calling it, is it also available locally, on http://localhost:3000? If so, update your JS to use the local version, not the remote one on path.to.cdn, and you avoid the whole problem!
This is just my rough guess about what wrong with your code can be.
I noticed you do:
a comparison of values from $headers but without
ensuring they have the same CAPITAL CASE as the values you compare against. Applied: strtoupper().
check with isset() but not test if key_exist before
Applied: key_exist()
check with isset() but perhaps you should use !empty() instead of isset()
compare result:
$value = "";
var_dump(isset($value)); // (bool) true
var_dump(!empty($value)); // (bool) false
$value = "something";
var_dump(isset($value)); // (bool) true
var_dump(!empty($value)); // (bool) true
unset($value);
var_dump(isset($value)); // (bool) false
var_dump(!empty($value)); // (bool) false
The code with applied changes:
<?php
error_reporting(E_ALL);
declare(strict_types=1);
header('Access-Control-Allow-Origin: *');
ob_start();
try {
$response = true;
if (!key_exists('url', $_GET)) {
$msg = '$_GET does not have a key "url"';
throw new \RuntimeException($msg);
}
$source = $_GET['url'];
if ($source !== filter_var($source, \FILTER_SANITIZE_URL)) {
$msg = 'Passed url is invaid, url: ' . $source;
throw new \RuntimeException($msg);
}
if (filter_var($source, \FILTER_VALIDATE_URL) === FALSE) {
$msg = 'Passed url is invaid, url: ' . $source;
throw new \RuntimeException($msg);
}
$headers = get_headers($source, 1);
if (!is_array($headers)) {
$msg = 'Headers should be array but it is: ' . gettype($headers);
throw new \RuntimeException($msg);
}
$headers = array_change_key_case($headers, \CASE_LOWER);
if ( key_exists('content-security-policy', $headers) &&
isset($headers['content-security-policy'])
) {
$response = false;
}
elseif ( key_exists('x-frame-options', $headers) &&
(
strtoupper($headers['x-frame-options']) == 'DENY' ||
strtoupper($headers['x-frame-options']) == 'SAMEORIGIN'
)
) {
$response = false;
}
} catch (Exception $ex) {
$response = "Error: " . $ex->getMessage() . ' at: ' . $ex->getFile() . ':' . $ex->getLine();
}
$phpOutput = ob_get_clean();
if (!empty($phpOutput)) {
$response .= \PHP_EOL . 'PHP Output: ' . $phpOutput;
}
echo $response;
Using Throwable instead of Exception will also catch Errors in PHP7.
Keep in mind that:
$response = true;
echo $response; // prints "1"
but
$response = false;
echo $response; // prints ""
so for the $response = false you'll get an empty string, not 0
if you want to have 0 for false and 1 for true then change the $response = true; to $response = 1; for true and $response = false; to $response = 0; for false everywhere.
I hope that somehow helps
I have a PHP method which retrieves data either from memcache, or from the database if it is not yet available there.
Sometimes the data must be loaded from the DB to update the memcache, for example if something changes.
public function get_likes_per_user($u_id, $force_db = false) {
if ($this->memcache) {
$u_id = intval($u_id);
$key = 'liked_news_' . $u_id;
$res = $this->memcache->get($key);
if ($res != '') {
$res = unserialize($res);
}
// This line causes a syntax error for no obvious reason
if(!is_array($res) || $force_db){
$res = array();
$sql = "...";
$uu_query = $this->datenbank->query_result($sql);
while ($row = $uu_query->fetch_row()) {
$res[] = $row['uu_id'];
}
$this->memcache->set($key, serialize($res), 0, 3600);
}
return $res;
} else {
throw new Exception("Kein Memcache Objekt!");
}
}
For some reason I don't understand php decides to throw a syntax error for the if statement which decides whether or not to reload the data from the DB.
I tried different notations for this statement but I can't figure out what causes the error.
Did anyone encounter something similar?
PHP Version 5.4
UPDATE:
I've found the cause of the error. I am working on a mac and to write a pipe charakter you have to press alt+7. If you press alt+spacebar mac OS X will insert a non-breaking space, which is invalid for PHP. So my mistake was to keep alt pressed after typing the two pipes for the OR statement.
Disclaimer; I'm fully aware of the pitfalls and "evils" of eval, including but not limited to: performance issues, security, portability etc.
The problem
Reading the PHP manual on eval...
eval() returns NULL unless return is
called in the evaluated code, in which
case the value passed to return is
returned. If there is a parse error in
the evaluated code, eval() returns
FALSE and execution of the following
code continues normally. It is not
possible to catch a parse error in
eval() using set_error_handler().
In short, no error capture except returning false which is very helpful, but I'm sur eI could do way better!
The reason
A part of the site's functionality I'm working on relies on executing expressions. I'd like not to pass through the path of sandbox or execution modules, so I've ended using eval. Before you shout "what if the client turned bad?!" know that the client is pretty much trusted; he wouldn't want to break his own site, and anyone getting access to this functionality pretty much owns the server, regardless of eval.
The client knows about expressions like in Excel, and it isn't a problem explaining the little differences, however, having some form of warning is pretty much standard functionality.
This is what I have so far:
define('CR',chr(13));
define('LF',chr(10));
function test($cond=''){
$cond=trim($cond);
if($cond=='')return 'Success (condition was empty).'; $result=false;
$cond='$result = '.str_replace(array(CR,LF),' ',$cond).';';
try {
$success=eval($cond);
if($success===false)return 'Error: could not run expression.';
return 'Success (condition return '.($result?'true':'false').').';
}catch(Exception $e){
return 'Error: exception '.get_class($e).', '.$e->getMessage().'.';
}
}
Notes
The function returns a message string in any event
The code expression should be a single-line piece of PHP, without PHP tags and without an ending semicolon
New lines are converted to spaces
A variable is added to contain the result (expression should return either true or false, and in order not to conflict with eval's return, a temp variable is used.)
So, what would you add to further aide the user? Is there any further parsing functions which might better pinpoint possible errors/issues?
Chris.
Since PHP 7 eval() will generate a ParseError exception for syntax errors:
try {
$result = eval($code);
} catch (ParseError $e) {
// Report error somehow
}
In PHP 5 eval() will generate a parse error, which is special-cased to not abort execution (as parse errors would usually do). However, it also cannot be caught through an error handler. A possibility is to catch the printed error message, assuming that display_errors=1:
ob_start();
$result = eval($code);
if ('' !== $error = ob_get_clean()) {
// Report error somehow
}
I've found a good alternative/answer to my question.
First of, let me start by saying that nikic's suggestion works when I set error_reporting(E_ALL); notices are shown in PHP output, and thanks to OB, they can be captured.
Next, I've found this very useful code:
/**
* Check the syntax of some PHP code.
* #param string $code PHP code to check.
* #return boolean|array If false, then check was successful, otherwise an array(message,line) of errors is returned.
*/
function php_syntax_error($code){
if(!defined("CR"))
define("CR","\r");
if(!defined("LF"))
define("LF","\n") ;
if(!defined("CRLF"))
define("CRLF","\r\n") ;
$braces=0;
$inString=0;
foreach (token_get_all('<?php ' . $code) as $token) {
if (is_array($token)) {
switch ($token[0]) {
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case T_START_HEREDOC: ++$inString; break;
case T_END_HEREDOC: --$inString; break;
}
} else if ($inString & 1) {
switch ($token) {
case '`': case '\'':
case '"': --$inString; break;
}
} else {
switch ($token) {
case '`': case '\'':
case '"': ++$inString; break;
case '{': ++$braces; break;
case '}':
if ($inString) {
--$inString;
} else {
--$braces;
if ($braces < 0) break 2;
}
break;
}
}
}
$inString = #ini_set('log_errors', false);
$token = #ini_set('display_errors', true);
ob_start();
$code = substr($code, strlen('<?php '));
$braces || $code = "if(0){{$code}\n}";
if (eval($code) === false) {
if ($braces) {
$braces = PHP_INT_MAX;
} else {
false !== strpos($code,CR) && $code = strtr(str_replace(CRLF,LF,$code),CR,LF);
$braces = substr_count($code,LF);
}
$code = ob_get_clean();
$code = strip_tags($code);
if (preg_match("'syntax error, (.+) in .+ on line (\d+)$'s", $code, $code)) {
$code[2] = (int) $code[2];
$code = $code[2] <= $braces
? array($code[1], $code[2])
: array('unexpected $end' . substr($code[1], 14), $braces);
} else $code = array('syntax error', 0);
} else {
ob_end_clean();
$code = false;
}
#ini_set('display_errors', $token);
#ini_set('log_errors', $inString);
return $code;
}
Seems it easily does exactly what I need (yay)!
How to test for parse errors inside eval():
$result = #eval($evalcode . "; return true;");
If $result == false, $evalcode has a parse error and does not execute the 'return true' part. Obviously $evalcode must not return itself something, but with this trick you can test for parse errors in expressions effectively...
Good news: As of PHP 7, eval() now* throws a ParseError exception if the evaluated code is invalid:
try
{
eval("Oops :-o");
}
catch (ParseError $err)
{
echo "YAY! ERROR CAPTURED: $err";
}
* Well, for quite a while then... ;)
I think that best solution is
try {
eval(/* ... */);
} catch (Throwable $t) {
//...
}
It catches every error and exception, including Call to undefined function etc
You can also try something like this:
$filePath = '/tmp/tmp_eval'.mt_rand();
file_put_contents($filePath, $evalCode);
register_shutdown_function('unlink', $filePath);
require($filePath);
So any errors in $evalCode will be handled by errors handler.