isset vs try/catch on namespaces - php

I'm parsing RSS feeds and have a (sub)function that looks like this:
function nSpace($nSp, $type, $i){
$namespaces = $i->getNameSpaces(true);
$exp = explode(':', $nSp);
try{
$nameSp = $i->children($namespaces[$exp[0]]);
$item[$type] = (string)$nameSp->$exp[1];
return $item[$type];
}
catch (Exception $e) { }
}
I'm trying to retrieve the namespace value, and will pass common RSS feed namespaces like "dc:date" or "content:encoded" for example as $nSp. The function works fine should the namespace exist in the XML, however the try{} is producing an 'Undefined Index' error in the first line when it doesn't.
Personally I'd rather run an isset($i->children($namespaces[$exp[0]])){} check instead of the try/catch, as I'm more familiar with that workflow, however this doesn't work (get a 'Can't use return value' error).
Few questions:
Shouldn't the try{} not produce error messages?
Is try/catch the best way?
Is there a way to do it with an if() instead?
Thanks.
Update:
Here is the (abreviated) call/usage for this function:
$rawFeed = file_get_contents($url);
try { $rss = new SimpleXMLElement($rawFeed); } catch (Exception $e) { }
foreach ($rss->channel->item as $i) {
$item['link'] = isset($i->link) ? (string)$i->link : nSpace('dc:link', 'link', $i);
$item['dateRaw'] = isset($i->pubDate) ? (string)$i->pubDate : nSpace('dc:date', 'date', $i);
// etc...
}

Related

php foreach - try catch, I don't know why I get 500 Error. I have call activeMQ

php foreach - try catch, I don't know why I get 500 Error.
in my code, I used this way to call activeMQ, but I will get 500 Error. I don't know what's happen.
This code only run to $url = "tcp://".$url; cannot run to uder try{}. Where is issues?
$stomp = null;
$mqUser='aaa';
$mqPasswd='aaa';
foreach ($urls as $url) {
$url = "tcp://".$url;
//echo $url." stomp status: null;<br />";
try {
$stomp = new Stomp($url);
} catch(Exception $e) {
}
if ($stomp) {
break;
}
}

PHP COM and CrystalReports

I'm trying to export a CrystalReports report using PHP and save it to the server. I'm using PHP's COM class. I'm not able to get it to work, it just hangs on Export(true). My code is as follows:
$obj = new COM('CrystalReports13.ObjectFactory.1') or die('1');
$get = $obj->CreateObject('CrystalDesignRunTime.Application') or die('2');
$report = $get->OpenReport('C:\\xampp\htdocs\\crystal\\Packslip_RepSrv.rpt', 1) or die('3');
try {
$report->Database->ConvertDatabaseDriver('crdb_odbc.dll', false);
$report->Database->Tables(1)->SetLogOnInfo('REMOVED', 'REMOVED', 'REMOVED','REMOVED');
$report->EnableParameterPrompting = 0;
$report->DiscardSavedData;
$report->ParameterFields->Item(1)->AddCurrentValue('9455');
$report->ExportOptions->DiskFileName='report.pdf';
$report->ExportOptions->FormatType=31;
$report->ExportOptions->DestinationType=1;
$report->Export(false);
$report = null;
$get = null;
$obj = null;
print "<embed src=\"report.pdf\">";
} catch(Exception $e) {
var_dump($e);
}
Does anything above look out of the usual? To my knowledge I'm doing everything properly, but it hangs on the $report->Export(false); part.
Don't use CrystalDesignRunTime
Use CrystalRunTime

Class to manipulate .ini files in php

I've been playing around with a php class I found on the net called Config Magik that I use to store some info in a INI file but have recently run into some problems when using removeKey. I wanted to know if someone can point me to a similar class that would work as well or better. Or if there is a better way to go about this.
This is my function right now, after playing around with it like crazy, so it is probably very faulty.
require_once('class.ConfigMagik.php');
$config = new ConfigMagik('config.ini', true, true);
if(!empty($_GET)){
if(!is_writeable('config.ini')){
echo 'Could not write to config.ini';
return false;
}
//if there is no section parameter, we will not do anything.
if(!isset($_GET['section'])){
echo false; return false;
} else {
$section_name = $_GET['section'];
unset($_GET['section']); //Unset section so that we can use the GET variable to manipulate the other parameters in a foreach loop.
if (!empty($_GET)){
foreach ($_GET as $var => $value){
echo $var.'='.$_GET[$var].'<br />';
//Check if said variable $var exists in the section.
if($config->get($var, $section_name) !== NULL){
//Set variable value.
try{
$config->set($var, $value, $section_name);
echo 'Setting variable '. $var.' to '.$value.' on section '.$section_name;
} catch(Exception $e) {
echo 'Could not set variable '.$var;
echo $e;
return false;
}
} else {
echo $var.' does not exist <br />';
}
}
}
try{
$section = $config->get($section_name); //Get the entire section so that we can manipulate it.
echo '<pre>';print_r($section);echo '</pre>';
foreach ($section as $title=>$value){
if(!isset($_GET[$title]) && isset($section[$title])){
try{
$config->removeKey($title, $section_name);
echo '<b>'.$title.'</b>: removed <br />';
} catch(Exception $e){
echo $e;
}
}
}
} catch(Exception $e){
echo $e;
}
$config->save();
//echo $config->toString('HTML');
echo true;
return true;
}
} else { RUN SOME HTML }
It basically saves the settings I pass on from the GET parameters and if the parameters are not there it is supposed to delete it. When I get to $config->removeKey($title, $section_name); in the last try catch statement it won't save automatically (as it should), so I tried running $config->save() and I ended up with a ini file that had section = array everywhere. Any advice will be appreciated as I've been learning PHP on the web for the last few weeks so I believe I've got a ways to go.
I have definitely isolated the problem to the $config->save() part, just don't know how to solve it.
Thanks in advance.
I have been using Zend_Config_Ini and Zend_Config_Writer_Ini in the past and was satisfied with the features. You will have extract the whole library/Zend/Config folder from Zend Framework and make Zend_Exception available though.

What's wrong with this try catch?

function rseo_get_seo($check, $post){
//code breaks somewhere in here. or in the rseo_doTheParse function.
switch ($check)
{
case "h1": return rseo_doTheParse('h1', $post);
case "h2": return rseo_doTheParse('h2', $post);
case "h3": return rseo_doTheParse('h3', $post);
case "img-alt": return rseo_doTheParse('img-alt', $post);
}
}
function rseo_doTheParse($heading, $post){
try { //I get a FATAL error here. unexpected '{'
$content = $post->post_content;
if ($content == "") return false;
$keyword = trim(strtolower(rseo_getKeyword($post)));
#$dom = new DOMDocument;
#$dom->loadHTML(strtolower($post->post_content));
$xPath = new DOMXPath(#$dom);
switch ($heading)
{
case "img-alt": return $xPath->evaluate('boolean(//img[contains(#alt, "'.$keyword.'")])');
default: return $xPath->evaluate('boolean(/html/body//'.$heading.'[contains(.,"'.$keyword.'")])');
}
}
catch (Exception $e)
{
echo 'Exception caught: ', $e->getMessage(), "\n";
}
}
The only thing I can think of is that you're on PHP 4, which doesn't support exception handling. So it thinks try is some kind of constant, but doesn't expect a { to be there.
You should have gotten a parse error, not a fatal error.
That code is 100% valid. Perhaps the error is elsewhere. On a side note, DOM functions don't throw exceptions--you might want to look into libxml_use_internal_errorsand set it up to throw exceptions.
I've pasted the code in a new file and ran it: no error. The problem might be above your code?
Line 14 after the switch block. Remove the second } just before the catch block

PHP eval and capturing errors (as much as possible)

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.

Categories