XML Postback issue - php

I have a script that is designed to parse XML postbacks from Ultracart, right now just dumps it into a MySQL table. The script works fine if I point it to a XML file on my localhost but using 'php://input' it doesn't seem to grabbing anything. My logs show apache returning 200 after the post so I have no idea what could be wrong or how to drill down the issue.. here's the code:
$doc = new DOMDocument();
$doc->loadXML($page);
$handle = fopen("test2/".time().".xml", "w+");
fwrite($handle,trim($page)); // it doesn't save this either :'(
fclose();
require_once('includes/database.php');
$db = new Database('localhost', 'user', 'password', 'db_name');
$data = array();
$exports = $doc->getElementsByTagName("export");
foreach ($exports as $export) {
$orders = $export->getElementsByTagName("order");
foreach($orders as $order) {
$data['order_id'] = $order->getElementsByTagName("order_id")->item(0)->nodeValue;
$data['payment_status'] = $order->getElementsByTagName("payment_status")->item(0)->nodeValue;
$date_array = explode(" ",$order->getElementsByTagName("payment_date_time")->item(0)->nodeValue);
if ($date_array[1] == 'JAN') { $date_array[1] = '01'; }
if ($date_array[1] == 'FEB') { $date_array[1] = '02'; }
if ($date_array[1] == 'MAR') { $date_array[1] = '03'; }
if ($date_array[1] == 'APR') { $date_array[1] = '04'; }
if ($date_array[1] == 'MAY') { $date_array[1] = '05'; } // converts Ultracart date to
if ($date_array[1] == 'JUN') { $date_array[1] = '06'; } // MySQL date
if ($date_array[1] == 'JUL') { $date_array[1] = '07'; }
if ($date_array[1] == 'AUG') { $date_array[1] = '08'; }
if ($date_array[1] == 'SEP') { $date_array[1] = '09'; }
if ($date_array[1] == 'OCT') { $date_array[1] = '10'; }
if ($date_array[1] == 'NOV') { $date_array[1] = '11'; }
if ($date_array[1] == 'DEC') { $date_array[1] = '12'; }
$data['payment_date'] = $date_array[2]."-".$date_array[1]."-".$date_array[0];
$data['payment_time'] = $date_array[3];
//... we'll skip this, there are 80 some elements
$data['discount'] = $order->getElementsByTagName("discount")->item(0)->nodeValue;
$data['distribution_center_code'] = $order->getElementsByTagName("distribution_center_code")->item(0)->nodeValue;
}
}
}
$db->insert('order_history',$data);
} else die('ERROR: Token Check Failed!');

Without seeing the code above that point, I'd suggest that you dump the output straight out and see if you're actually receiving the XML. I doubt the problem is with your parsing, but with receiving the postback. Looking at the ultracart documentation, it looks to me like they aren't passing the the body of the xml in as a post parameter, but probably as an HTTP PUT which is fairly whacky.
http://php.net/manual/en/features.file-upload.put-method.php
I'd wager on most shared hosting etc, PUT support is pretty limited or not supported by default. I'd look there first.
Josh

The script works fine if I point it to a XML file on my localhost but using 'php://input' it doesn't seem to grabbing anything.
Why would you expect php://input to "grab anything"? You can use php://input only to read from the standard input if PHP is being run from the command line or to fetch the request data (e.g. POST or PUT HTTP request data), except for a multipart POST.

Related

PHP page stops loading halfway through - Doesn't finish code

I have a web application where I look through all mails in the inbox of my Gmail-account and search for specific strings to pick out different emails.
On this app I can set a limit on how many emails to search. If I set this limit to "200" or lower it works just fine most of the times.
But if i increase the limit to 400 and up that, 99% of the times, the application/page stops loading. And the code doesn't finish.
I have enabled so PHP shows error messages via the host website and also via this code at the begining of each php page:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
?>
However, when the page stops loading, no error messages is displayed. (And it does display on other errors)
This is the code I'm using, together with Gmail API.
<?php
//Authentication with Gmail API happens here
$gmail = new Google_Service_Gmail($client);
$number_of_emails_to_fetch = 500;
$list = $gmail->users_messages->listUsersMessages('me', ['maxResults' => $number_of_emails_to_fetch]);
$filename = "unsubscribe-show-all.php";
$sql_table_name = create_table();
$connection = open_connection();
while ($list->getMessages() != null) {
foreach ($list->getMessages() as $mlist) {
$message_id = $mlist->id;
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me', $message_id, $optParamsGet2);
$payload = $single_message->getPayload();
$parts = $payload->getParts();
// With no attachment, the payload might be directly in the body, encoded.
$body = $payload->getBody();
$FOUND_BODY = FALSE;
// If we didn't find a body, let's look for the parts
if(!$FOUND_BODY) {
foreach ($parts as $part) {
if($part['parts'] && !$FOUND_BODY) {
foreach ($part['parts'] as $p) {
if($p['parts'] && count($p['parts']) > 0){
foreach ($p['parts'] as $y) {
if(($y['mimeType'] === 'text/html') && $y['body']) {
$FOUND_BODY = decodeBody($y['body']->data);
break;
}
}
} else if(($p['mimeType'] === 'text/html') && $p['body']) {
$FOUND_BODY = decodeBody($p['body']->data);
break;
}
}
}
if($FOUND_BODY) {
break;
}
}
}
// If we didn't find the body in the last parts,
// let's loop for the first parts (text-html only)
if(!$FOUND_BODY) {
foreach ($parts as $part) {
if($part['body'] && $part['mimeType'] === 'text/html') {
$FOUND_BODY = decodeBody($part['body']->data);
break;
}
}
}
// With no attachment, the payload might be directly in the body, encoded.
if(!$FOUND_BODY) {
$FOUND_BODY = decodeBody($body['data']);
}
if(!$FOUND_BODY) {
$FOUND_BODY = '(No message)';
}
}
?>
After this code I have more code that handles inserting different links into databases followed by a redirection.
However, i tried removing that code and only running the code above + the redirection, but the page still stops loading, so I figure it has something to do with this snippet.
Any advice on where to read, or hints on how to fix this would be greatly appreciated!

php include or require contents of a variable, not a file

I'm looking for a way to include or require the content of a variable, instead of a file.
Normally, one can require/include a php function file with either of these:
require_once('my1stphpfunctionfile.php')
include('my2ndphpfunctionfile.php');
Suppose I wanted to do something like this:
$contentOf1stFFile = file_get_contents('/tmp/my1stphpfunctionfile.php');
$contentOf2ndFFile = file_get_contents('/tmp/my2ndphpfunctionfile.php');
require_once($contentOf1stFFile);
require_once($contentOf2ndFFile);
Now, in the above example, I have the actual function files which I am loading into variables. In the real world scenario I'm actually dealing with, the php code in the function files are not stored in files. They're in variables. So I'm looking for a way to treat those variables as include/require treats the function files.
I'm new to php so please forgive these questions if you find them foolish. What I'm attempting to do here does not appear to be possible. What I ended up doing was using eval which I'm told is very dangerous and should be avoided:
eval("?>$contentOf1stFFile");
eval("?>$contentOf2ndFFile");
Content of $contentOf1stFFile:
# class_lookup.php
<?php
class Lookup_whois {
// Domain name which we want to lookup
var $domain;
// TLD for above domain, eg. 'com', 'net', etc...
var $tld;
// Array which contains information needed to parse the whois server response
var $tld_params;
// Sets to error code if something fails
var $error_code;
// Sets user-friendly error message if something goes wrong
var $error_message;
// For internal use mainly - raw response from the whois server
var $whois_raw_output;
function Lookup_whois($domain, $tld, $tld_params) {
$this->domain = $domain;
$this->tld = $tld;
$this->tld_params = $tld_params;
}
function check_domain_spelling() {
if (preg_match("/^([A-Za-z0-9]+(\-?[A-za-z0-9]*)){2,63}$/", $this->domain)) {
return true;
} else {
return false;
}
}
function get_whois_output() {
if (isset($this->tld_params[$this->tld]['parameter'])) {
$query = $this->tld_params[$this->tld]['parameter'].$this->domain.'.'.$this->tld;
} else {
$query = $this->domain.'.'.$this->tld;
}
$server = $this->tld_params[$this->tld]['whois'];
if (!$this->check_domain_spelling()) {
$this->error_message = 'Domain name is not correct, check spelling. Only numbers, letters and hyphens are allowed';
return false;
}
if (!$server) {
$this->error_message = 'Whois server name is empty, please check the config file';
return false;
}
$output = array();
$fp = fsockopen($server, 43, $errno, $errstr, 30);
if(!$fp) {
$this->error_code = $errno;
$this->error_message = $errstr;
fclose($fp);
return false;
} else {
sleep(2);
fputs($fp, $query . "\n");
while(!feof($fp)) {
$output[] = fgets($fp, 128);
}
fclose($fp);
$this->whois_raw_output = $output;
return true;
}
}
function parse_whois_data() {
if (!is_array($this->whois_raw_output) && Count($this->whois_raw_output) < 1) {
$this->error_message = 'No output to parse... Get data first';
return false;
}
$wait_for = 0;
$result = array();
$result['domain'] = $this->domain.'.'.$this->tld;
foreach ($this->whois_raw_output as $line) {
#if (ereg($this->tld_params[$this->tld]['wait_for'], $line)) {
if (preg_match($this->tld_params[$this->tld]['wait_for'],$line)) {
$wait_for = 1;
}
if ($wait_for == 1) {
foreach ($this->tld_params[$this->tld]['info'] as $key => $value) {
$regs = '';
if (ereg($value.'(.*)', $line, $regs)) {
if (key_exists($key, $result)) {
if (!is_array($result[$key])) {
$result[$key] = array($result[$key]);
}
$result[$key][] = trim($regs[1]);
} else {
$result[$key] = trim($regs[1]);
$i = 1;
}
}
}
}
}
return $result;
}
}
?>
Are there any other alternatives?
No there are no other alternatives.
In terms of security there is no difference if you include() a file or eval() the content. It depends on the context. As long as you only run your own code there is nothing "dangerous".

Why strpos PHP not work with fsockopen response?

Why strpos PHP not work with fsockopen response ?
When load this code. This code will be requests sdgsgsdgsfsdfsd.ca to whois.cira.ca server and find text Domain status: available with strpos PHP if found it's will be echo
{"domain":"sdgsgsdgsfsdfsdca","availability":"available"}
but if not found text. It's will be echo
{"domain":"sdgsgsdgsfsdfsdca","availability":"TAKEN"}
In this case found text but still echo
{"domain":"sdgsgsdgsfsdfsdca","availability":"TAKEN"}
How can i do ?
<?php
$server = "whois.cira.ca";
$response = "Domain status: available";
showDomainResult(sdgsgsdgsfsdfsd.ca,$server,$response);
function checkDomain($domain_check,$server,$findText)
{
$con = fsockopen($server, 43);
if (!$con) return false;
fputs($con, $domain_check."\r\n");
$response = ' :';
while(!feof($con))
{
$response .= fgets($con,128);
}
echo $response."<BR><BR><BR><BR><BR>";
fclose($con);
if (strpos($response, $findText))
{
return true;
}
else
{
return false;
}
}
function showDomainResult($domain_check,$server,$findText)
{
if (checkDomain($domain_check,$server,$findText))
{
class Emp
{
public $domain = "";
public $availability = "";
}
$e = new Emp();
$e->domain = $domain_check;
$e->availability = "available";
echo json_encode($e);
}
else
{
class Emp
{
public $domain = "";
public $availability = "";
}
$e = new Emp();
$e->domain = $domain_check;
$e->availability = "TAKEN";
echo json_encode($e);
}
}
?>
you're using strpos wrong, if the string START with what you're searching for, it will return int(0), which is "kinda false" by PHP's definition. explicitly check for false, like this
return false!==strpos($response, $findText);
and make sure you're using !== not !=
and as a rule of thumb, never use loose comparison operators in PHP if you can avoid it, hilarious bugs can occur if you do: https://3v4l.org/tT4l8

Get return values of code with tokenizer

I'm trying to parse PHP source code with the token_get_all(). So far everything worked out with that function, but now i need a way to get the return values of methods.
Identifying where a return is done isn't the problem. I just see no way of getting the piece of code that comes after the return value.
For example for this piece of code:
<?php
class Bla {
public function Test1()
{
$t = true;
if($t) {
return 1;
}
return 0;
}
public function Test2()
{
echo "bbb";
return; // nothing is returned
}
public function Test3()
{
echo "ccc";
$someval1 = 1;
$someval2 = 2;
return ($someval + $otherval)*2;
}
}
?>
I'm using get_token_all() to identify where a return is done:
$newStr = '';
$returnToken = T_RETURN;
$tokens = token_get_all($source);
foreach ($tokens as $key => $token)
{
if (is_array($token))
{
if (($token[0] == $returnToken))
{
// found return, now get what is returned?
}
else
{
$token = $token[1];
}
}
$newStr .= $token;
}
I have no clue how to get the piece of code that is actually returned. That is what i want to get.
Anyone any idea how i could do this?
Perhaps this might help. Though I curious to know what you are ultimately trying to do.
$tokens = token_get_all($str);
$returnCode = '';
$returnCodes = array();
foreach ($tokens as $token) {
// If return statement start collecting code.
if (is_array($tokens) && $token['0'] == T_RETURN) {
$returnCode .= $token[1];
continue;
}
// if we started collecting code keep collecting.
if (!empty($returnCode)) {
// if we get to a semi-colon stop collecting code
if ($token === ';') {
$returnCodes[] = substr($returnCode, 6);
$returnCode = '';
} else {
$returnCode .= isset($token[1]) ? $token[1] : $token;
}
}
}

Baffled as to why PHP is giving simple logic error on if statement

Like the title says, PHP is really confusing me on a simple if comparison statement that's returning the opposite of what it should be returning. I'm trying to compare 2 datetime's that are first converted to strings:
//Fetched db query, this returns 2012-06-23 16:00:00
$databaseDateTime = strtotime($row['time']);
//This now returns 1340481600
//today's date and time I'm comparing to, this returns 2012-06-22 17:14:46
$todaysDateTime = strtotime(date("Y-m-d H:i:s"));
//this now returns 1340399686
Great, everything works perfect so far. Now here's where things get hairy:
if ($databaseDateTime < $todaysDateTime) { $eventType = 'past'; }
And this returns 'past', which of course it shouldn't. Please tell me I'm missing something. My project kind of depends on this functionality being airtight.
**EDIT***
Thanks guys for taking the time to help me out. Let me post the entire code because a few of you need more context. The request is coming from an IOS5 to my backend code and json is being sent back to the phone.
<?php
//all included files including $link to mysqli_db and function sendResponse()
function getEvents($eventType, $eventArray) {
global $link;
global $result;
global $i;
global $todaysDateTime;
foreach ($eventArray as $key => $value) {
$sqlGetDeal = mysqli_query($link, "SELECT time FROM deals WHERE id='$value' AND active='y' LIMIT 1") or die ("Sorry there has been an error!");
while ($row = mysqli_fetch_array($sqlGetDeal)) {
//compare times to check if event already happened
$databaseDateTime = strtotime($row['time']);
if ($databaseDateTime < $todaysDateTime) { $eventType = 'past'; }
$result[$i] = array(
'whenDeal' => $eventType,
'time' => $databaseDateTime,
);
$i++;
}//end while
}//end foreach
}
if (isset($_GET['my'])) {
//$_GET['my'] comes in as a string of numbers separated by commas e.g. 3,2,6,3
$myDeals = preg_replace('#[^0-9,]#', '', $_GET['my']);
$todaysDateTime = strtotime(date("Y-m-d H:i:s"));
$result = array();
$kaboomMy = explode(",", $myDeals);
$i = 1;
if ($myEvents != "") {
getEvents('future', $kaboomMy);
}//end if
sendResponse(200, json_encode($result));
} else {
sendResponse(400, 'Invalid request');
} //end $_POST isset
?>
Found a quick hack around the issue. I just added a local variable to my function and rearranged my compare statement
//added local variable $eventTyppe to function
$eventTyppe;
changed compare from:
if ($databaseDateTime < $todaysDateTime) { $eventType = 'past'; }
to:
if ($todaysDateTime < $databaseDateTime ) {
$eventTyppe = $eventType;
} else {
$eventTyppe = 'past';
}
Notice if I rearrange compare:
if ($databaseDateTime < $todaysDateTime ) {
$eventTyppe = 'past';
} else {
$eventTyppe = $eventType;
}
I still get the same error. This is the weirdest thing I've ever seen and the first PHP bug I've run into (I'm assuming it's a PHP bug).
Could you print the values of the times right before this line?
if ($databaseDateTime < $todaysDateTime) { $eventType = 'past'; }
Since that one is declared as global I'm wondering if is it coming back incorrectly.

Categories