geofiltering to provide location based content - php

I wish to provide location based content i.e I want to allow only users located in Arizona to view the video displayed on my page. However users outside Arizona are also able to view the page.I am using http://freegeoip.net web service to determine users locations from their IP addresses.
This is the code embedded in the webpage
<?php require_once("geofilter.php"); ?>
<?php
if (getRegion()=="Arizona")
//if (getCity()=="Tempe" || getCity()=="Chandler")
{
?>
<iframe src = 'videourl' height='415' width='615' align='top' scrolling='no' frameborder='0'></iframe>
<?php
} else
{
?>
<h1 style="color:#F00">This page is not available in your region: <?php echo (getCity().", ".getRegion());?></h1>
<?php }?>
this is the code for geofilter.php
<?php
function getCountry()
{
$pageContent = file_get_contents('http://freegeoip.net/json/');
$parsedJsonCountry = json_decode($pageContent);
return htmlspecialchars($parsedJsonCountry->country_name);
}
function getRegion()
{
$pageContent = file_get_contents('http://freegeoip.net/json/');
$parsedJsonRegion = json_decode($pageContent);
return htmlspecialchars($parsedJsonRegion->region_name);
}
function getCity()
{
$pageContent = file_get_contents('http://freegeoip.net/json/');
$parsedJsonCity = json_decode($pageContent);
return htmlspecialchars($parsedJsonCity->city);
}
function getZipCode()
{
$pageContent = file_get_contents('http://freegeoip.net/json/');
$parsedJsonZip = json_decode($pageContent);
return htmlspecialchars($parsedJsonZip->zipcode);
}
function getIpAddress()
{
$pageContent = file_get_contents('http://freegeoip.net/json/');
$parsedJsonIp = json_decode($pageContent);
return htmlspecialchars($parsedJsonIp->ip);
}
?>

Do you not need to be passing the client's IP address to this service somehow? From the looks of it, you are just calling a remote endpoint from your server, which without passing client information, would just give the IP address of your server.
I would have thought that even very rudimentary debugging on your part would have shown that you get the same exact results for every call made to the service endpoint from your server.
Also, that code is really poorly structured. There is no reason to potentially call this service for each country, region, etc. determination. Just make the call once up front and store all the Geoip determination information.
So here would be my suggestion:
$client_ip_address = $_SERVER['REMOTE_ADDR']; // or however you get client IP
$geoip_json = file_get_contents('http://freegeoip.net/json/' . $client_ip_address);
$geoip = json_decode($geoip_json);
// you now have geoip object you can work directly with
// no need for a bunch of function wrappers
// example
// $country_name = $geoip->country_name;
if ($geoip->region_code === 'AZ') {
// do whatever
}
Finally, is making a remote service call really what you want to do? It may be OK if you are not expecting a lot of traffic or concerned over the time it takes to load your pages, however, there is no reason you should not be able to use a local GeoIP database to perform these lookups. Take a look at something like this, for better options: https://github.com/maxmind/. Maxmind even offers Apache modules that will have the effect of exposing GeoIP information in $_SERVER superglobal.

Related

Prestashop Quick Address Links to external URL

I have a small problem on the prestashop on adding custom url into the quick address.
The current status of prestashop is 1.7.4.2 fresh install.
As stated from the image above, I would like to redirect it to external URL http://www.google.com, after done creating it is shown in the quick address menu as shown below:
But when I clicked it, just redirect to:
http://localhost:8080/prestashop_1.7.4.2/admin067c8ousl/index.php/http://www.google.com
Note I have deleted the token as it provided the same result
In other words the token is self generated and differs everytime
I have saw original documentation for that specific issue in here.
When you see on the very bottom, it shows the exact issue I am facing:
Note that you can create links to other websites, for instance your PayPal account or your webmail. Simply paste the complete URL in the "URL" field, including the http:// prefix.
As I have written correct url, but it still thinks it is a controller.
I have no modified any code yet, is there a way to fix it.
Thank You and Have a nice day.
That was for v1.6, v1.7 doesn't allow external urls by default. I submitted an improvement for this, hope they approve the merge. Meanwhile, if you want to use them you can modify the classes/QuickAccess.php or add to the override (better option) and change the function getQuickAccessesWithToken to the following:
public static function getQuickAccessesWithToken($idLang, $idEmployee)
{
$quickAccess = self::getQuickAccesses($idLang);
if (empty($quickAccess)) {
return false;
}
$baselink = Context::getContext()->link->getBaseLink();
foreach ($quickAccess as $index => $quick) {
if(strpos($quickAccess[$index]['link'], 'http') !== 0 or strpos($quickAccess[$index]['link'], $baselink) === 0){
if ('../' === $quick['link'] && Shop::getContext() == Shop::CONTEXT_SHOP) {
$url = Context::getContext()->shop->getBaseURL();
if (!$url) {
unset($quickAccess[$index]);
continue;
}
$quickAccess[$index]['link'] = $url;
} else{
// first, clean url to have a real quickLink
$quick['link'] = Context::getContext()->link->getQuickLink($quick['link']);
$tokenString = $idEmployee;
preg_match('/controller=(.+)(&.+)?$/', $quick['link'], $admin_tab);
if (isset($admin_tab[1])) {
if (strpos($admin_tab[1], '&')) {
$admin_tab[1] = substr($admin_tab[1], 0, strpos($admin_tab[1], '&'));
}
$quick_access[$index]['target'] = $admin_tab[1];
$tokenString = $admin_tab[1].(int)Tab::getIdFromClassName($admin_tab[1]).$idEmployee;
}
$quickAccess[$index]['link'] = $baselink.basename(_PS_ADMIN_DIR_).'/'.$quick['link'];
if (false === strpos($quickAccess[$index]['link'], 'token')) {
$separator = strpos($quickAccess[$index]['link'], '?') ? '&' : '?';
$quickAccess[$index]['link'] .= $separator.'token='.Tools::getAdminToken($tokenString);
}
}
}
}
return $quickAccess;
}
Override is not a clean solution.
You can use free module to adding jquery to your "admin header hook" and do it by jquery to change URL of new created quickAccess

Cloud hosting causing issues with JSON retrieval?

I'm hosted with Smarthosting, they used cloud based hosting which delivers faster loading times - great!
But I have a snag.
I'm setting some sessions via PHP in a seperate file...
<?php
session_start();
if(filter_var($_POST['question_1'], FILTER_VALIDATE_INT)) {
$_SESSION['question_1'] = addslashes($_POST['question_1']);
}
if(filter_var($_POST['question_2a'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2a'] = addslashes($_POST['question_2a']);
}
if(filter_var($_POST['question_2b'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2b'] = addslashes($_POST['question_2b']);
}
if(filter_var($_POST['question_2c'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2c'] = addslashes($_POST['question_2c']);
}
if(filter_var($_POST['question_2d'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2d'] = addslashes($_POST['question_2d']);
}
if(filter_var($_POST['question_2e'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2e'] = addslashes($_POST['question_2e']);
}
if(filter_var($_POST['question_2f'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2f'] = addslashes($_POST['question_2f']);
}
if(filter_var($_POST['question_2g'], FILTER_VALIDATE_INT)) {
$_SESSION['question_2g'] = addslashes($_POST['question_2g']);
}
?>
Then later on I access another PHP file which puts these into a JSON string...
<?php
session_start();
echo json_encode($_SESSION);
?>
This works fine, however, until I call the JSON via Ajax...
$.getJSON( "retrieve-variables.php", function( data ) {
var items = [];
...etc....
});
It's not pulling the most recent session data, it seems to pull back the session data from previous attempts. Is this to do with the cloud hosting? Or some other issue? Is there a way I can disable caching for this particular file and/or entire directory?
Thanks for listening.
EDIT: If I access the PHP retrieval file directly, then hard refresh it (CTRL+F5), and then go through the form again, it will ignore the answers I've selected and enter the data for that hard refresh I did
I found out how to fix this, in case anyone stumbles upon this post.
I simple added cache:"false" to the ajax get request.

calling ajax from within a php function having a switch ($this->method)

when creating an XMLrequest in a php file having a code which goes something like this... I am using a MVC ( model-view-controller structure ) and this is a controller php file..
Controller_Institute extends Controller_Default{
function register(){
try {
$this->requireLogin();
switch($this->method){
case 'GET':
$content = $this->render('institute_registration_confirm');
break;
case 'POST':
$result = mysql_query("SELECT * FROM password WHERE pass='".mysql_real_escape_string($_POST['pass'])."'");
$num=mysql_num_rows($result);
if($num==2)
{
$content = $this->render('institute_registration');
}
else
{
$content = $this- >render("message",array('msg'=>'Your password is incorrect'));
}
break;
}
$institute = R::dispense('institute');
$institute- >import($_POST,'name,latitude,state,longitude,address,phone,year,url');
$id = R::store($institute);
}
catch(exception $e){
//If there was an error anywhere, go to the error page.
$content = $this->render('error',array('exception'=>$e));
}
$page = $this->render('default',array('content'=>$content));
return $page;
}
i am sending the ajax request from within the function ... so when the ajax sends back the request , it gets caught in the switch case... and then the response text becomes the function return value replacing the actual text... any idea how to prevent the xml response from getting into the switch case...? the institute_registration is the view file and i am including that file in my framework and then triggering the ajax function from within that file to check whether the password ( to enable registration form ) is correct or not...
Given the limited information and pseudo-code, I recommend setting up a stand-alone page called say... "ajax.php" that is stand alone and doesn't base it's return value on the request method. The pages that use AJAX will need to either POST or GET from this page depending.
If you determine whether or not regular output vs AJAX output is returned via request method, then you are limiting yourself in 2 ways. The first is you will not be able to do 1 or the other on your web pages (GET vs POST) instead of both. Also, the second, when it comes to the AJAX, you will not be able to run GET & POST AJAX requests, and yes, you can do both with AJAX: http://net.tutsplus.com/tutorials/javascript-ajax/5-ways-to-make-ajax-calls-with-jquery/

PHP redirection issue

I have a program that prints reports for a user id list. The program is supposed to print reports one by one for users on the list uploaded. The problem is that when I was running the printing process and getting to print the report with indexInList=30, I got error:
This webpage has a redirect loop
The webpage at http://127.0.0.1/content/8520?print=1&bulkprinting=1&filename=/private/var/tmp/phpHRXEw8.moved&indexInList=30&nopeergroup=1&nolabpage=0&hideScreeningOnly=1&showOnlyScreening=0&hideHoldMailing=1 has resulted in too many redirects. Clearing your cookies for this site or allowing third-party cookies may fix the problem. If not, it is possibly a server configuration issue and not a problem with your computer.
I tried to clean the cookie but still keep getting the same error.
I attached some code here and hope anyone can help me:
$sessionData['first_name'] = $foundUser->first_name;
$sessionData['last_name'] = $foundUser->last_name;
// Overwrite $_REQUEST variable with parameters before including
// the hpa report
$_REQUEST = array(
'user_id' => $foundUser->id,
'bulkprinting' => true
);
if($nopeergroup) { $_REQUEST['nopeergroup'] = $nopeergroup; }
if($nolabpage) { $_REQUEST['nolabpage'] = $nolabpage; }
if($hideScreeningOnly) { $_REQUEST['hideScreeningOnly'] = $hideScreeningOnly; }
if($showOnlyScreening) { $_REQUEST['showOnlyScreening'] = $showOnlyScreening; }
if($hideHoldMailing) { $_REQUEST['hideHoldMailing'] = $hideHoldMailing; }
$includeValue = include __DIR__.'/../hpa/hpa.php';
$url = sprintf(
"/content/8520?print=1&bulkprinting=1&filename=%s&indexInList=%s" .
"&nopeergroup=%s&nolabpage=%s&hideScreeningOnly=%s" .
"&showOnlyScreening=%s&hideHoldMailing=%s",
$filename, $indexInList, (int)$nopeergroup, (int)$nolabpage,
(int)$hideScreeningOnly, (int)$showOnlyScreening, (int)$hideHoldMailing);
if($hradata[0] !== false) {
$sessionData['hra_id'] = $hradata[0]['id'];
}
if($screeningdata[0] !== false) {
$sessionData['screening_id'] = $screeningdata[0]['id'];
}
if($includeValue !== 1) {
// Redirect to URL
$sessionData['message'] = $messages_set[$includeValue];
$_SESSION['printing_set'][] = $sessionData;
redirect($url);
}
$sessionData['markAsMailed'] = true;
$_SESSION['printing_set'][] = $sessionData;
?>
<script type="text/javascript">
function waitPrint() {
window.print();
var t = setTimeout("timed()", 1000);
}
function timed() {
window.location.replace("<?php echo $url ?>");
}
if(window.attachEvent) {
window.attachEvent("onload", waitPrint);
} else if(window.addEventListener) {
window.addEventListener("load", waitPrint, false);
}
</script>
Sounds like you have a lot of files that need printing!
You may be able to alter your browser settings (I seem to remember you can in Firefox) to allow more than 30 loops.
Alternatively, you could always limit your code to 30 loops then wait for further user interaction to proceed to the next 30.
The 3rd option is to always create a Word document or PDF with one report on each page, then save the file and print it - a little more hassle (in a way) but at least you'll be able to print everything at once.
In order for $includeValue to be set to anything, the file __DIR__.'/../hpa/hpa.php' must have a return statement inside of it, as demonstrated in the PHP documentation for include, example 5. include will only return a value when called if the included file returns a value.
If your script still produces an infinite loop, your logic within the included file is incorrect and it is consistently producing a value that is not 1.
Essentially, here is the code that your question boils down to:
$includeValue = include __DIR__.'/../hpa/hpa.php';
if($includeValue !== 1) {
// Redirect
}
Browsers have checks built-in to help you when sites are misconfigured into a redirection loop, and 30 must be the limit for the browser you're using. You've built a redirection loop on purpose, but the browser doesn't know that. Instead of using the window.location.replace() method, how about a form that automatically submits? That should look different to the browser, and allow your loop to progress as designed.
<script type="text/javascript">
function waitPrint() {
window.print();
var t = setTimeout("timed()", 1000);
}
function timed() {
window.reloadForm.submit();
}
if(window.attachEvent) {
window.attachEvent("onload", waitPrint);
} else if(window.addEventListener) {
window.addEventListener("load", waitPrint, false);
}
</script>
<form name="reloadForm" action="<?php echo $url ?>">
</form>

Need help to rewrite PHP function

I have a function that parses text form posts and if there's a link in the post it'll redirect the link to a page that warns a users about external link before they click it.
function url2link($txt) {
$setUrl = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '$2$4', $txt);
return $setUrl;
}
I need to modify this function by adding a check for domain in the link. If the link is from my own domain, just convert it into clickable link like this:
$setUrl = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '$2$4', $txt);
but if it is a link to an external domain -- make a link point to a warning page (top example).
I am sort of stuck here because I have no idea how to add this check. There could be multiple links in a post, some may have local, some external links and some a mix.
Try with preg_replace_callback, then you can process the matches to decide whether it's your own domain or some other.
OK, as it turned out preg_replace_callback was exactly what I needed in this case. php.net documentation sucks. I found another article that made it clear what it is and how it works. I modified my function but it doesn't work... What am I missing?
function url2link($txt) {
$checkDomain = preg_replace_callback('/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/', 'linkDomain', $txt);
function linkDomain($matches) {
$host = parse_url($matches[0], PHP_URL_HOST);
$host = ltrim($host, 'www.');
if ($host == 'mydomain.com') {
$setUrl = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '$2$4', $matches[0]);
} else {
$setUrl = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '$2$4', $matches[0]);
}
}
return $setUrl;
}

Categories