Background:
I've created a website that displays currency rates from various countries. I use Google's currency converter API to perform the calculations.
http://www.google.com/ig/calculator?h1=en&q=9999gbp=?usd
Notice the query I have passed in e.g. 9999 Great British Pounds to United States Dollars.
The API returns:
{lhs: "9999 British pounds",rhs: "15 769.4229 U.S. dollars",error: "",icc: true}
Google has separated the 15 769.4229 with white space between the 5 and the 7.
This causes a problem when I return the results of a calculation on my site as the white space char is replaced with the � symbol.
See screen shot below:
Any ideas what this symbol is called so I can attempt to remove it?
<?php
// Check to ensure that form has been submitted
if (isset($_POST['amount'], $_POST['from'], $_POST['to'])) {
$amount = trim($_POST['amount']);
$from = $_POST['from'];
$to = $_POST['to'];
try {
$conversion = currency_convert($googleCurrencyApi, $amount, $from, $to);
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage();
}
// Check URL has been formed
if ($conversion == false) {
echo 'Sorry, something went wrong';
} else {
echo $conversion[0], ' = ', $conversion[1];
}
}
function currency_convert($googleCurrencyApi, $amount, $from, $to) {
$result = file_get_contents($googleCurrencyApi . $amount . $from . '=?' . $to);
$expl = explode('"', $result);
if ($expl[1] == '' || $expl[3] == '') {
throw new Exception('An error has occured. Unable to get file contents');
} else {
return array(
$expl[1],
$expl[3]
);
}
}
?>
Here's my code so far at the moment, so you get the idea behind my logic.
This is most probably non-breaking space, try replacing into space:
$result = file_get_contents($googleCurrencyApi . $amount . $from . '=?' . $to);
$result = str_replace("\xA0", " ", $result);
Try modifying your code so that you're UTF8 decoding the data that's being returned from Google:
// Check URL has been formed
if ($conversion == false) {
echo 'Sorry, something went wrong';
} else {
echo utf8_decode($conversion[0]), ' = ', utf8_decode($conversion[1]);
}
I'm presuming that your default encoding is ISO-8859-1
EDIT
(As per comments) The issue may be that you have been sent a null character. Try this:
$result = str_replace("\0", "", $result );
or
$result = str_replace("", "", $result );
After str_replace do:
$result_amt = utf8_decode($amount);
You will get the ? character instead of space. So then use str_replace again to remove ? character:
$result =str_replace("?","", $result_amt );
Related
I have the following code which works great to do what it is meant to do. It scrapes bodys of all e-mails in the inbox at an e-mail address using IMAP and retrieves the unique code sent inside the body and stores it in a database with the amount paid. I'm hoping to make it so when a user purchases something they can send an Interac e-transfer and then enter the code that both of us receive via e-mail in the website and it will apply the credit of the e-transfer to their account/purchase.
However; after setting it up on a cron job to cycle every few minutes so the content in the database stays fresh it eventually exceeds the bandwidth for the account within a day or so (not positive on how long it took but it didn't take long). Now, like I said the code works it's just very resource intensive apparently.
I do not pipe the script because the e-mail account has already been set up a while ago and we do use the account for other e-transfers which I review manually for other transactions.
Is there anyway to clean it up so it works the same but uses less resources/bandwidth?
Would it be better to run it when a user enters their payment code? Depending on the number of users running it this could also lead to bandwidth troubles.
Is there any improvements or what ideas do you have?
define("MAX_EMAIL_COUNT", $_POST['maxcount']);
/* took from https://gist.github.com/agarzon/3123118 */
function extractEmail($content) {
$regexp = '/([a-z0-9_\.\-])+\#(([a-z0-9\-])+\.)+([a-z0-9]{2,4})+/i';
preg_match_all($regexp, $content, $m);
return isset($m[0]) ? $m[0] : array ();
}
function getAddressText(&$emailList, &$nameList, $addressObject) {
$emailList = '';
$nameList = '';
foreach ($addressObject as $object) {
$emailList .= ';';
if (isset($object->personal)) {
$emailList .= $object->personal;
}
$nameList .= ';';
if (isset($object->mailbox) && isset($object->host)) {
$nameList .= $object->mailbox . "#" . $object->host;
}
}
$emailList = ltrim($emailList, ';');
$nameList = ltrim($nameList, ';');
}
function processMessage($mbox, $messageNumber) {
global $db;
// get imap_fetch header and put single lines into array
$header = imap_rfc822_parse_headers(imap_fetchheader($mbox, $messageNumber));
$timestamp = strtotime($header->Date);
$fromEmailList = '';
$fromNameList = '';
if (isset($header->from)) {
getAddressText($fromEmailList, $fromNameList, $header->from);
}
$toEmailList = '';
$toNameList = '';
if (isset($header->to)) {
getAddressText($toEmailList, $toNameList, $header->to);
}
$body = imap_fetchbody($mbox, $messageNumber, 1);
//echo "<pre>".print_r($body,true)."</pre>";
/* Find Reference Number */
//echo "<pre style='background-color: #A2A2A2; border: 1px solid black'>$body</pre>";
$searchfor = 'Reference Number';
// get the file contents, assuming the file to be readable (and exist)
$contents = $body;
// escape special characters in the query
$pattern = preg_quote($searchfor, '/');
// finalise the regular expression, matching the whole line
$pattern = "/^.*$pattern.*\$/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)){
$reference = trim(str_replace('Reference Number : ','',$matches[0][0]));
}
else{
}
/* Find Amount Paid */
//echo "<pre style='background-color: #A2A2A2; border: 1px solid black'>$body</pre>";
$searchfor = 'has sent you a money transfer for the amount of';
// get the file contents, assuming the file to be readable (and exist)
$contents = $body;
// escape special characters in the query
$pattern = preg_quote($searchfor, '/');
// finalise the regular expression, matching the whole line
$pattern = "/^.*$pattern.*\$/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)){
$amount = trim(preg_replace("/[^0-9\.]/", "",$matches[0][0]),'.');
}
else{
}
$bodyEmailList = implode(';', extractEmail($body));
// Delete all messages older than one year (31557600 seconds). Divide it by two for six months.
if($timestamp < time()-31557600) {
if(imap_delete($mbox,$messageNumber)) {
/*echo "<strong>";
print_r($messageNumber . ' , ' . date("F j, Y g:i A",$timestamp).' , ' . 'Deleted' . "\n");
echo "</strong>";*/
}
}
else {
if(!empty($reference) && !empty($amount)) {
if($fromNameList == "catch#payments.interac.ca" && $toNameList!='etransfers#example.com') {
$query = "SELECT * FROM `".$db->prefix."payments_etransfer` WHERE `reference_id` = '".$reference."'";
$select = $db->select($query);
if($db->num_rows($select) > 0) {
}
else {
$do = $db->insert_sql("INSERT INTO `".$db->prefix."payments_etransfer` SET
`email_id` = '".$messageNumber."',
`timestamp` = '".$timestamp."',
`reference_id` = '".$reference."',
`amount` = '".$amount."',
`sender` = '".$fromEmailList."'");
if($do) {
}
else {
echo "Error<br><blockquote><pre>";
print_r($messageNumber . ',' . $timestamp. ',' . $reference . ',$' . $amount .
',' . $fromEmailList . ',' . $fromNameList
. ',' . $toEmailList . ',' . $toNameList
. ',' . $bodyEmailList . "\n"
);
echo "</pre></blockquote>";
}
}
}
}
}
}
// imap_timeout(IMAP_OPENTIMEOUT, 300);
// Open pop mailbox
if (!$mbox = imap_open($_POST['mailbox'], $_POST['login'], $_POST['password'])) {
die('Cannot connect/check pop mail! Exiting');
}
if ($hdr = imap_check($mbox)) {
$msgCount = $hdr->Nmsgs;
} else {
echo "Failed to get mail";
exit;
}
/* echo "<pre>";
echo 'emails count=' . $msgCount . "\n\n\n";
echo "record number,from emails list,from names list,to emails list, to names list,extracted from body\n";
*/
/* might improve performance according to
http://www.php.net/manual/en/function.imap-headerinfo.php#98809
imap_headers($mbox);
*/
for ($X = $msgCount; $X > 0; $X--) {
if($X > 0) {
processMessage($mbox, $X);
}
}
/*echo "</pre>";*/
imap_expunge($mbox);
imap_close($mbox);
/*
When a user adds $keyword into my chat application i want to remove the $ sign. $keyword is NOT a variable it is a string that contains $ to fire the keyword.
here is my code:
<?php
class Chat extends DB {
public function get_Messages() {
$rows = DB::getInstance()->query("SELECT * FROM ( SELECT user,message,TS FROM chat ORDER BY TS DESC LIMIT 50 ) sub ORDER BY TS ASC");
foreach ($rows->results() as $row) {
$str=$row->message;
$stocklist = '$AAPL'; << doenst convert to link when containing $
echo $row->TS . '<br/><strong>' .$row->user . '</strong> says: <br/>';
echo preg_replace("/(".$stocklist.")/s","<a href='http://finance.yahoo.com/q?s=$1'>$1</a>",$str) . '<br/><br/>';
}
}
public function send_Message($user, $message) {
if (!empty($user) && !empty($message)) {
$user = mysql_real_escape_string($user);
$message = mysql_real_escape_string($message);
$send = DB::getInstance()->insert('chat', array(
'id' => null,
'user' => $user,
'message' => $message
));
if ($send = true) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
I have sorted a few bugs out, now the only issue is that the string $APPL does not convert to link. if i change $AAPL to APPL then it converts to link. I require $AAPL as a link.
Thanks
OK I have modified my answer as per update in the question. Try this using preg_replace_callback():
$str = 'This is a $link this is not a link.';
$str = preg_replace_callback(
'/\$([a-z]+)/i',
function($match) {
$white_list = Array();// Array of all the valid links, any other match will not be replaced
return in_array($match[1], $white_list) ? (''.ucfirst($match[1]).'') : '$'.$match[1];
},
$str
);
var_dump($str); // Outputs: string(82) "This is a Link this is not a link."
I am working on a php script to pull quest data from wowhead, particularly what starts and ends the quest, whether it is an item or a npc, and what its id or name is, respectively. This is the relevant portion of the whole script, with the rest involving database insertion. This is the completed snippet of code I came up with if anyone is interested. Also, seeing as this will run about 15,000 times, is this the best method of obtaining/storing the data?
<?php
$quests = array();
//$questlimit = 14987;
$questlimit = 5;
$currentquest = 1;
$questsprocessed = 0;
while($questsprocessed != $questlimit)
{
echo "<br>";
echo " Start of iteration: ".$questsprocessed." ";
echo "<br>";
echo " Attempting to process quest: ".$currentquest." ";
echo "<br>";
$quests[$currentquest] = array();
$baseurl = 'http://wowhead.com/quest=';
$fullurl = $baseurl.$currentquest;
$data = drupal_http_request($fullurl);
$queststartloc1 = strpos($data->data, 'quest_start');
$queststartloc2 = strpos($data->data, 'quest_end');
if($queststartloc1==false)
{$currentquest++; echo "No data for this quest"; echo "<br>"; continue;}
$questendloc1 = strpos($data->data, 'quest_end');
$questendloc2 = strpos($data->data, 'x5DDifficulty');
$startcaptureLength = $queststartloc2 - $queststartloc1;
$endcaptureLength = $questendloc2 - $questendloc1;
$quest_start_raw = substr($data->data,$queststartloc1, $startcaptureLength);
$quest_end_raw = substr($data->data, $questendloc1, $endcaptureLength);
$startDecoded = preg_replace('~\\\\x([A-Fa-f0-9]{2})~e', 'chr("0x$1")', $quest_start_raw);
$endDecoded = preg_replace('~\\\\x([A-Fa-f0-9]{2})~e', 'chr("0x$1")', $quest_end_raw);
$quests[$currentquest]['Start'] = array();
$quests[$currentquest]['End'] = array();
if(strstr($startDecoded, 'npc'))
{
$quests[$currentquest]['Start']['Type'] = "npc";
preg_match('~npc=(\d+)~', $startDecoded, $startmatch);
}
else
{
$quests[$currentquest]['Start']['Type'] = "item";
preg_match('~item=(\d+)~', $startDecoded, $startmatch);
}
$quests[$currentquest]['Start']['ID'] = $startmatch[1];
if(strstr($endDecoded, 'npc'))
{
$quests[$currentquest]['End']['Type'] = "npc";
preg_match('~npc=(\d+)~', $endDecoded, $endmatch);
}
else
{
$quests[$currentquest]['End']['Type'] = "item";
preg_match('~item=(\d+)~', $endDecoded, $endmatch);
}
$quests[$currentquest]['End']['ID'] = $endmatch[1];
//var_dump($quests[$currentquest]);
echo " End of iteration: ".$questsprocessed." ";
echo "<br>";
echo " Processed quest: ".$currentquest." ";
echo "<br>";
$currentquest++;
$questsprocessed++;
}
?>
These are called "escape sequences". Normally, they're used to represent characters not printable otherwise, but can encode any character. In php, you can decode them like this:
$text = '
quest_start\\x5DStart\\x3A\\x20\\x5Bitem\\x3D16305\\x5D\\x5B\\x2Ficon\\x5D\\x5B\\x2Fli\\x5D\\x5Bli\\x5D\\x5Bicon\\x20name\\x3Dquest_end\\x5DEnd\\x3A\\x20\\x5Burl\\x3D\\x2Fnpc\\x3D12696\\x5DSenani\\x20Thunderheart\\x5B\\x2Furl\\x5D\\x5B\\x2Ficon\\x5D\\x5B\\x2Fli\\x5D\\x5Bli\\x5DNot\\x20sharable\\x5B\\x2Fli\\x5D\\x5Bli
';
$decoded = preg_replace('~\\\\x([A-Fa-f0-9]{2})~e', 'chr("0x$1")', $text);
Which gives you a string similar to this:
quest_start]Start: [item=16305][/icon][/li][li][icon name=quest_end]End: [url=/npc=12696]Senani Thunderheart[/url][/icon][/li][li]Not sharable[/li][li
(obviously, some kind of BB-code). To remove all bbcodes, yet one replacement is necessary:
$clean = preg_replace('~(\[.+?\])+~', ' ', $decoded);
I am using https://github.com/davideme/libphonenumber-for-PHP for formatting phonenumbers
I am having issue with 1800 numbers
$formatnumber = "1800123456"
$country = "AU";
$phoneUtil = PhoneNumberUtil::getInstance();
try {
$NumberProto = $phoneUtil->parse( $formatnumber , $country );
} catch ( NumberParseException $e ) {
echo $e;
}
$formattedNumber = $phoneUtil->format( $NumberProto, PhoneNumberFormat::NATIONAL );
What I am expecting to get back from $formattedNumber is "1800 123456"
What I get back is an unformatted number "1800123456"
If there something I need to do doing to get it to format correctly?
It works for me with pretty much your code:
<?php
require __DIR__ . '/vendor/autoload.php';
$formatnumber = "1800123456";
$country = "AU";
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
try {
$NumberProto = $phoneUtil->parse($formatnumber, $country);
} catch (NumberParseException $e) {
echo $e;
}
$formattedNumber = $phoneUtil->format($NumberProto, \libphonenumber\PhoneNumberFormat::NATIONAL);
echo $formattedNumber;
Response:
1800 123 456
I am using my version of libphonenumber-for-php though: https://github.com/giggsey/libphonenumber-for-php
I have a latitude and a longitude, and I need to fetch country.
I am using this:
$geocode_stats = file_get_contents("http://maps.googleapis.com/maps/api/geocode/json?latlng=".$deal_lat.",".$deal_long . "&sensor=false");
$output_deals = json_decode($geocode_stats);
$country = $output_deals->results[2]->address_components[4]->long_name;
Sometimes it gives a correct country name, but sometimes it gives blank values, and sometimes it returns a city name.
Can anybody help?
I wrote a function to make it easy. Simply pass in your geo-address which can be a full address, zip code, or in your case latitude and longitude. It will then search through the address component array for the country. In the case that it is unable to find the county it will simply return null, you can change that to an empty string ("") if you need to.
function getGeoCounty($geoAddress) {
$url = 'http://maps.google.com/maps/api/geocode/json?address=' . $geoAddress .'&sensor=false';
$get = file_get_contents($url);
$geoData = json_decode($get);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Invalid geocoding results');
}
if(isset($geoData->results[0])) {
foreach($geoData->results[0]->address_components as $addressComponent) {
if(in_array('administrative_area_level_2', $addressComponent->types)) {
return $addressComponent->long_name;
}
}
}
return null;
}
Get complete Address from latitude and longitude.
$url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng='.trim($lat).','.trim($lng).'&sensor=false';
$json = #file_get_contents($url);$data=json_decode($json);
echo $data->results[0]->formatted_address;
$deal_lat=30.469301;
$deal_long=70.969324;
$geocode=file_get_contents('http://maps.googleapis.com/maps/api/geocode/json?latlng='.$deal_lat.','.$deal_long.'&sensor=false');
$output= json_decode($geocode);
for($j=0;$j<count($output->results[0]->address_components);$j++){
$cn=array($output->results[0]->address_components[$j]->types[0]);
if(in_array("country", $cn)){
$country= $output->results[0]->address_components[$j]->long_name;
}
}
echo $country;
$deal_lat=30.469301;
$deal_long=70.969324;
$geocode=file_get_contents('http://maps.googleapis.com/maps/api/geocode/json?latlng='.$deal_lat.','.$deal_long.'&sensor=false');
$output= json_decode($geocode);
for($j=0;$j<count($output->results[0]->address_components);$j++){
$cn=array($output->results[0]->address_components[$j]->types[0]);
if(in_array("country", $cn)){
$country= $output->results[0]->address_components[$j]->long_name;
}
}
echo $country;
I did take the code of matwonk as base.
function getGeoCounty($geoAddress) {
$url = 'http://maps.google.com/maps/api/geocode/json?address=' . urlencode($geoAddress) .'&sensor=false';
$get = file_get_contents($url);
$geoData = json_decode($get);
if(isset($geoData->results[0])) {
$return = array();
foreach($geoData->results[0]->address_components as $addressComponet) {
if(in_array('political', $addressComponet->types)) {
if($addressComponet->short_name != $addressComponet->long_name)
$return[] = $addressComponet->short_name. " - " . $addressComponet->long_name;
else
$return[] = $addressComponet->long_name;
}
}
return implode(", ",$return);
}
return null;
}
The code return in format: neighborhood, City, State, Country
if detect a shortname (as country code or state code) appear in format CODE - NAME.
$latlng = '22.7314,75.88243';
$request_url = "http://maps.googleapis.com/maps/api/geocode /xml?latlng=".$latlng."&sensor=true";
$xml = simplexml_load_file($request_url);
if($xml->status == "OK") {
$address = $xml->result->formatted_address;
foreach ($xml->result->address_component as $address) {
if("country" == trim($address->type)) {
$country = $address->short_name;
}
}
}