Odd issue with PHP namespace - php

I have slapped together a test PHP script. It would output some remote connection's geo ip based data. Nothing fancy, just a quick prototype.
But I am seeing an odd behavior, so I am asking here if somebody had any clues about it.
PHP is version 5.5.12 on Ubuntu 64 bit.
Here's some code from the geoip_test.php calling script:
require_once ('geoip_utils.php');
$server_geoip_record = geoip_record_by_name('php.net');
echo '<pre>PHP.net web server location: ' . print_r($server_geoip_record, 1);
echo '<br />PHP.net web server local time: ' . \df_library\getUserTime($server_geoip_record)->format('Y-m-d H:i:s');
Nothing fancy at all, isn't it?
Now the simple geoip_utils.php code:
<?php
namespace df_library;
require_once('timezone.php');
// Given an IP address, returns the language code (i.e. en)
function getLanguageCodeFromIP($input_ip)
{
};
// Given a geo_ip_record, it returns the local time for the location indicated
// by it. In case of errors, it will return the optionally provided fall back value
function getUserTime($geoip_record, $fall_back_time_zone = 'America/Los_Angeles') {
//Calculate the timezone and local time
try
{
//Create timezone
$timezone = #get_time_zone($geoip_record['country_code'], ($geoip_record['region'] != '') ? $geoip_record['region'] : 0);
if (!isset($timezone)) {
$timezone = $fall_back_time_zone;
}
$user_timezone = new \DateTimeZone($timezone);
//Create local time
$user_localtime = new \DateTime("now", $user_timezone);
}
//Timezone and/or local time detection failed
catch(Exception $e)
{
$user_localtime = new \DateTime("now");
}
return $user_localtime;
}
?>
When I run the calling script I get:
PHP Fatal error: Call to undefined function df_library\getUserTime() in /var/www/apps/res/geoip_test.php on line 5
The funny part is: if I add this debug code:
$x = get_defined_functions();
print_r($x["user"]);
I get this output:
Array
(
[0] => df_library\getlanguagecodefromip
[1] => df_library\gettimezone
[2] => df_library\getutcdatetime
[3] => df_library\getlocalizedtime
[4] => df_library\getutcdatetimeaslocalizeddatetime
[5] => df_library\getlocalizeddatetimeasutcdatetime
[6] => get_time_zone
)
First of all, I don't understand why the function names are converted to lower case.
But most of all, notice how index 0 shows the empty function function getLanguageCodeFromIP($input_ip) being defined, and that function is right above the one that the interpreter complains about as not being defined!
Why does PHP see the other function in that file but not the one I want to use?
Any ideas are welcome!

There is an extra semi-colon ; after the close bracket of function getLanguageCodeFromIP which causes PHP parser somehow unable to recognize the functions after getLanguageCodeFromIP.
As proven in OP's comment, removing the ; solved the problem.

Related

cPanel Parked Domains Not returning array

A password was changed and cPanel broke. Fixed the password and it's still broken! I have to iterate over parked domains. I've verified the user / password combination is correct via PuTTY.
<?php
include_once('cpanel_api_xml.php');
$domain = 'example.com';
$pass = '';//etc
$user = '';//etc
$xmlapi = new xmlapi('127.0.0.1');
$xmlapi->password_auth($user,$pass);
$domains_parked = $xmlapi->listparkeddomains($user);
foreach ($domains_parked as $k1=>$v1)
{
if ($v1->domain == $domain) {$return = true; break;}
}
?>
That code generates the following error:
Invalid argument supplied for foreach()
Apparently $domains_parked is not even set! I've spent time looking at the function being called so without dumping all 86KB here is the cleaned up version of $xmlapi->listparkeddomains:
<?php
public function listparkeddomains($username, $domain = null)
{
$args = array();
if (!isset($username))
{
error_log("listparkeddomains requires that a user is passed to it");
return false;
}
if (isset($domain))
{
$args['regex'] = $domain;
return $this->api2_query($username, 'Park', 'listparkeddomains', $args);
}
return $this->api2_query($username, 'Park', 'listparkeddomains');
}
?>
I don't know what they're doing with setting a variable as the second parameter. I've called this function with and without and tested the reaction with a simple mail().
Next I tried calling the API in a more direct fashion:
$xmlapi->api2_query($username, 'Park', 'listparkeddomains')
That also does not work. Okay, let's try some really raw output testing:
echo "1:\n";
print_r($xmlapi);
echo "2:\n";
print_r($xmlapi->api2_query($user, 'Park', 'listparkeddomains'));
echo "3:\n";
$domains_parked = $xmlapi->listparkeddomains($user);
print_r($domains_parked);
die();
That outputs the following:
1: xmlapi Object (
[debug:xmlapi:private] =>
[host:xmlapi:private] => 127.0.0.1
[port:xmlapi:private] => 4099
[protocol:xmlapi:private] => https
[output:xmlapi:private] => simplexml
[auth_type:xmlapi:private] => pass
[auth:xmlapi:private] => <pass>
[user:xmlapi:private] => <user>
[http_client:xmlapi:private] => curl ) 2: 3:
I have never encountered such fragile code though I have no choice but to use it. Some help please?
So cPanel version 74 killed off the whole XML API and it doesn't frigin tell you with any error messages. I can not objectively say in the least that cPanel provides a stable platform to build anything reliable upon. You can either intentionally gimp your server from automatically updating (and potentially miss out on security updates) or every so X iterations of time completely rewrite the code again...and again...and again.

Using Dynamic Variable Names to Call Static Variable in PHP

I am trying to implement a logging library which would fetch the current debug level from the environment the application runs in:
23 $level = $_SERVER['DEBUG_LEVEL'];
24 $handler = new StreamHandler('/var/log/php/php.log', Logger::${$level});
When I do this, the code fails with the error:
A valid variable name starts with a letter or underscore,followed by any number of letters, numbers, or underscores at line 24.
How would I use a specific Logger:: level in this way?
UPDATE:
I have tried having $level = "INFO" and changing ${$level} to $$level. None of these changes helped.
However, replacing the line 24 with $handler = new StreamHandler('/var/log/php/php.log', Logger::INFO); and the code compiles and runs as expected.
The variable itself is declared here
PHP Version => 5.6.99-hhvm
So the answer was to use a function for a constant lookup:
$handler = new StreamHandler('/var/log/php/php.log', constant("Monolog\Logger::" . $level));
<?php
class Logger {
const MY = 1;
}
$lookingfor = 'MY';
// approach 1
$value1 = (new ReflectionClass('Logger'))->getConstants()[$lookingfor];
// approach 2
$value2 = constant("Logger::" . $lookingfor);
echo "$value1|$value2";
?>
Result: "1|1"

Catchable fatal error: Argument 1 passed to CorenlpAdapter::getOutput()

I get the following error:
Catchable fatal error: Argument 1 passed to CorenlpAdapter::getOutput() must be an instance of string, string given, called in /Library/WebServer/Documents/website/php-stanford-corenlp-adapter/index.php on line 22 and defined in /Library/WebServer/Documents/website/php-stanford-corenlp-adapter/src/CoreNLP/CorenlpAdapter.php on line 95
index.php 21 and 22 contain:
$text1 = 'I will meet Mary in New York at 10pm';
$coreNLP->getOutput($text1);
corenlpAdapter.php lines 95 and onwards contain:
public function getOutput(string $text){
if(ONLINE_API){
// run the text through the public API
$this->getServerOutputOnline($text);
} else{
// run the text through Java CoreNLP
$this->getServerOutput($text);
}
// cache result
$this->serverMemory[] = $this->serverOutput;
if(empty($this->serverOutput)){
echo '** ERROR: No output from the CoreNLP Server **<br />
- Check if the CoreNLP server is running. Start the CoreNLP server if necessary<br />
- Check if the port you are using (probably port 9000) is not blocked by another program<br />';
die;
}
/**
* create trees
*/
$sentences = $this->serverOutput['sentences'];
foreach($this->serverOutput['sentences'] as $sentence){
$tree = $this->getTreeWithTokens($sentence); // gets one tree
$this->trees[] = $tree; // collect all trees
}
/**
* add OpenIE data
*/
$this->addOpenIE();
// to get the trees just call $coreNLP->trees in the main program
return;
}
Why exactly am I getting this error when text1 is a string?
I am the original author of this class. As you can see, the function getOutput looks like this:
public function getOutput(string $text){
...
}
Change that to:
public function getOutput($text){
...
}
The function tries to enforce that the input is string. The original code should work. However, it seems that in your case, PHP thinks "string" is not actually a string. Maybe the coding environment (the IDE) you are using uses the wrong character set? Or maybe you copy-pasted the code from HTML into the IDE or something like that. Thus whilst it says "string" on the screen, it's not actually a string to PHP.
If you are sure the input is a string, you can safely change the code like above. The class should then work normally.
public function getOutput($text){
.
.
.
}

Storing an object to database and then retrieving it back again

Please excuse the long post - I've tried to be as succinct as possible, whilst giving as much detail as I can ... and I've historically been a procedural PHP programmer, now getting my feet wet with objects.
I'm working on a test project where I'm using a 3rd party class (loaded via phar) to capture a stream from an online server. The online server posts events, I capture (using "capture.php") each event with the 3rd party class, serialize the data and then store it to a MySQL database as a BLOB field.
//capture.php
// include phar file
require_once 'PAMI-1.72.phar';
// set include path to have pami's phar first
ini_set('include_path', implode(PATH_SEPARATOR, array('phar://pami.phar', ini_get('include_path'))));
use PAMI\Client\Impl\ClientImpl as PamiClient;
use PAMI\Message\Event\EventMessage;
use PAMI\Listener\IEventListener;
$pamiClient = new PamiClient($pamiClientOptions);
// Open the connection
$pamiClient->open();
$pamiClient->registerEventListener(function (EventMessage $event) {
// Following line dumps the event to a text file in rawCapture.php
//var_dump($event);
$mysqli = new mysqli($server, $user, $pass, $db);
if ($mysqli->connect_error) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
exit;
}
$serializedData = $mysqli->real_escape_string(serialize($event));
$sql = 'insert into obj (data) values ("' . $serializedData . '")';
echo "\r\nSQL is $sql\r\n";
});
In a different script ("read.php" - I know - I'm VERY creative in script naming) I ensure that I have the include files to the class definition files, pick up the first entry in the database, pull the BLOB data and then unserialize it. At this point I'm testing the variable type in read.php and the variable is an object:
require_once 'PAMI-1.72.phar';
// set include path to have pami's phar first
ini_set('include_path', implode(PATH_SEPARATOR, array('phar://pami.phar', ini_get('include_path'))));
use PAMI\Client\Impl\ClientImpl as PamiClient;
use PAMI\Message\Event\EventMessage;
use PAMI\Listener\IEventListener;
/* All the MySQL stuff to get the $data from the db */
$event = unserialize($data);
echo "\r\nevent is " . gettype($event) . "\r\n";
print_r($event);
And this is the result I get:
event is object
PAMI\Message\Event\NewchannelEvent Object
(
[rawContent:protected] => Event: Newchannel
Privilege: call,all
Channel: Local/s#tc-maint-00006a43;2
ChannelState: 4
ChannelStateDesc: Ring
CallerIDNum:
CallerIDName:
AccountCode:
Exten: s
Context: tc-maint
Uniqueid: 1443368640.57856
[lines:protected] => Array
(
)
[variables:protected] => Array
(
)
[keys:protected] => Array
(
[event] => Newchannel
[privilege] => call,all
[channel] => Local/s#tc-maint-00006a43;2
[channelstate] => 4
[channelstatedesc] => Ring
[calleridnum] =>
[calleridname] =>
[accountcode] =>
[exten] => s
[context] => tc-maint
[uniqueid] => 1443368640.57856
)
[createdDate:protected] => 1443368636
)
Ok - so far so good, IMHO. This certainly appears to be an object, all the data certainly appears to have been stored correctly (rawCapture.php is another script which also polls the data and var_dumps the same events out to a text file, so that I can "compare" and ensure that everything is being recorded correctly).
However, now I want to deal with some of the object data and this is where I'm having issues. For example, I'm trying to obtain the value of the Uniqueid, but using $id = $event->Uniqueid; I get the following error PHP Notice: Undefined property: PAMI\Message\Event\NewchannelEvent::$Uniqueid in /home/dave/objRead.php on line 69
Now I'm stuck. I've tried checking that $event is in fact an object, using get_object_vars():
$objVars = get_object_vars($event);
if(is_null($objVars)){
echo "\r\nobjVars doesn't appear to be an object?!\r\n";
} else {
if(is_array($objVars)){
print_r($objVars);
} else {
echo "\r\nobjVars isn't an array!!\r\n";
}
}
and I'm getting my own error code "objVars doesn't appear to be an object?!".
Can anyone give me some advice on what on earth I'm doing wrong??
Also - I've tried to keep indentation in the code sections above but it wouldn't let me post without removing them. I've also amended my OP to show that I'm including the 3rd party code so that the class definitions are loaded, and the line that I use to unserialize the data from the MySQL table.
Have you tried changing the case of Uniqueid in $id = $event->Uniqueid; to lower case? So it would be $id = $event->uniqueid;

PHP Error on Code it should not be running

First let me say sorry for the amount of code I'm posting below I'm going to try and keep it as short as possible but this is built on top of my MVC (lightweight-mvc)
Ok So my Problem is that for some reason php is throwing a fatal error on code that should not be being used in my current code,
So how this works I have my MVC witch used the first 2 parts of the url to know what its loading, the problem is I'm building a Moulder CMS into my MVC so it's boot strapping twice,
So here is my Problem,
http://{domain}/admin/control/addon/uploader/method/uploadCheck/
I'm using the above now let me explain a little into that the /admin/control are for the main MVC System it auto-loads the Admin controller then fires the controlAction method from the controller much the same as most MVC's,
The next part are URL paramters that build an array the same as GET or POST would
array('addon'=>'uploader', 'method'=>'uploadCheck')
So from that my control action will auto load as is the code below
public function controlAction(){
global $_URL;
if(cleanData::URL("addon")){
$addonName = "addon_".cleanData::URL("addon");
$methodName = (cleanData::URL("method"))? cleanData::URL("method")."Action" : "indexAction";
echo $methodName;
$addon = new $addonName();
$addon->$methodName();
return;
}else{
$this->loadView("CMS/controll");
}
}
cleanData::URL is an abstract method that just returns the value of the key provided though addSlashes()
So as you can see from the code below it will then use the autoloader to load the module(AKA addon)
Just so you can follow the auto loader works in a simpler version of the Zend Frame work autoloader _ so you have class name addon_admin that would be inside file admin.php that is in the folder addon so the autoloader will load addon/admin.php
So As above with my URL and controlAction it's loading addon/uploader.php and as such this is the contents
<?php
class addon_uploader extends Addons{
public function uploadCheckAction(){
echo 0;
}
public function uploaderAction(){
if (!empty($_FILES)) {
$tmpFile = $_FILES['Filedata']["tmp_name"];
$newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']);
move_uploaded_file($tmpFileName, $newLock);
$POSTback = array(
'name' => $_FILES['Filedata']['name'],
'type' => $_FILES['Filedata']['type'],
'tmp_name' => $newLock,
'error' => $_FILES['Filedata']['error'],
'size' => $_FILES['Filedata']['size']
);
echo json_enocde($POSTback);
}
}
}
?>
But as you can see from my URL its using the uploadCheckAction method witch for debugging i have set so it always says false (AKA 0),
But i seem to get this error:
Fatal error: Only variables can be passed by reference in C:\xampp\htdocs\FallenFate\addon\uploader.php on line 11
But line 11 is $newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']); witch should not be being used could any one provide any help into why this would occur and how i could fix it
end() PHP Manual needs an expression of a single variable (more precisely an array), but not a function return value or any other type of expression.
I think that's basically the cause of your error, more specifically with your code:
$newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']);
you're even driving this far beyond any level of treatment PHP can cope with:
you concatenate an array with a string (which results in a string).
you run end() on that string - not on a variable, not even an array.
I have no clue what you try to do with the code, but I can try:
$filename = $_FILES['Filedata']['name'];
$parts = explode('/', $tmpFile);
$last = end($parts);
$newLock = "../uploads/". $last . $filename;
Or probably even only this:
$filename = $_FILES['Filedata']['name'];
$newLock = "../uploads/". $filename;

Categories