Header location infinite redirect Loop - php

I have this huge issue that I have no idea how to fix. I have a script that redirects to a url.
So far I have:
//do some mysql
$geo_included = true; //trying to fix infinite redirect loop.
if($geo_included === true){
header('Location: '.$url["url"]); //this is causing the issue with redirect loop
}
$url["url"] for example is: www.google.com
But when I go to that PHP file it will redirect to:
www.sitename.com/www.google.com
and say there is an infinite redirect loop. Note: the above header location script is not in a while/for/foreach loop.
Here is my .htaccess for the / directory
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?group=$1 [L]
Any ideas?

You need to include the fully qualified domain name with scheme, otherwise it's interpreted as being in the current domain:
header('Location: google.com'); // Redirects to http://cursite.com/www.google.com
header('Location: http://google.com'); // Redirects as expected
If you are unsure if your URL includes a scheme, check the results from parse_url.
$url_scheme = parse_url($url, PHP_URL_SCHEME);
// www.google.com -> NULL
// http://google.com -> string(4) "http"
// ftp://site.com -> string(3) "ftp"

The quick proof-of-concept solution here is to prepend http:// to the URL like this:
$geo_included = true;
if ($geo_included) {
header('Location: http://' . $url["url"]);
}
I say “proof of concept” because what you should do is ensure the $url["url"] always has a protocol attached to it. Either before it gets into the database, or in this code snippet by doing a check on the $url["url"] value to see of it has http:// or https:// and if it doesn’t, prepend it. And here is a quickly thrown together example of what I mean which should work:
$geo_included = true;
if ($geo_included) {
$protocol = (!preg_match("~^(?:ht)tps?://~i", $url["url"])) ? 'http://' : null;
header('Location: ' $protocol . $url["url"]);
}
The line with $protocol = … does the check I explained before. The default is to add http:// if it’s not there.
Also, note I removed === true since the if ($geo_included) { is basically the same thing.

Related

Create subdomains on the fly with info from database

I am trying to achieve automatic subdomain creation. I have read a lot of tutorials including:
THIS
THIS
THIS
I understood the concept and I implemented it with success in the past for user profiles, but this is a different case and I am stuck.
What I want to do, is basically something like pen.io as functionality. A user creates a page with a password and then, that page name converts into a subdomain.
I thought of doing a function that runs on the index page of the main website and that one used afterwards in HTACCESS to have something like index.php?subdomain=test and that one to redirect to test.domain.tld
EDIT:
Here is the current implementation that works when clicking on a link, but it doesn't work when accessing the url directly from the browser:
Code used in view.php:
<?php
include('inc/config.php');
$url = filter_var($_GET['url'], FILTER_SANITIZE_STRING);
$conn = new mysqli($server, $username, $password, $database) or die ('Unable to execute query. '. mysqli_error($conn));
$query = "SELECT * FROM `pages` WHERE pageTitle = '$url'";
$result = $conn->query($query);
if($row = mysqli_fetch_array($result))
{
$title = $row['pageEditableTitle'];
$content = $row['pageContent'];
echo '<h5 class="mt-5"><mark>'.$title.'</mark></h5>
<p class="lead display-7">'.$content.'</p>';
} else {
echo '<br /><div class="alert alert-info" role="alert">Subdomain does not exist.</div>';
}
$conn->close();
?>
Code used in htaccess:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.tld
RewriteRule ^(.*)$ https://domain.tld/view.php?url=%1 [L,NC,QSA]
But this redirects www.domain.tld to domain.tld/view.php?url=www and not staying as www.domain.tld in the browser url
I presuppose that you setup a wildcard dns entry (access random.domain.tld to test it!). Then you have two options:
Correct your rewrite rules
Something like [aA-zZ] should be [a-zA-Z] and the RewriteRule should be only after the RewriteCond and not in front of it and two of them. And do you really want to force a - inside the subdomain with ([a-z0-9][-a-z0-9]+)? Maybe you should check this answer. Note: The www inside of your domain is a subdomain as well. So it would rewrite to sub.php?url=www
With the corrected rewriting random.domain.tld returns the content of random.domain.tld/sub.php?url=random. But at the moment your sub.php does not return content. Instead it returns a http redirect to the URL random.domain.tld. This means your sub.php produces an infinite loop on itself. Instead sub.php should only contain something like <?php echo $_SERVER['HTTP_HOST']; ?>.
Maybe you did not understand how URL rewriting works. Then read this answer for further explanation.
Update1
You corrected your code as follows:
RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9]+)\.domain\.tld\.?(:80)?$ [NC]
RewriteRule ([a-zA-Z0-9]+) /view.php?url=$1
But it's still wrong. As I said you need to read and understand this answer. #JoachimIsaksson uses $1 and %1 in his 2nd example:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ /subdomains/%1/$1 [L,NC,QSA]
%1 is the subdomain catched through RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com. And $1 is the path catched through RewriteRule ^(.*)$. You missed to use %1.
But your code can not work as you forced an unempty alphanummeric string by RewriteRule ([a-zA-Z0-9]+). But a path could contain more than that. For example a slash or question mark. And of course it could be empty as well.
And why did you add (:80)?? Do you think someone will access your domain with a specific port?
And why the last optional dot in tld\.??
At last you need to bring the flags into question. You used the NC flag. It means your rule is case-insensitive. So why do you use [a-zA-Z0-9]? As your rule is already case-insensitive it can be [a-z0-9]. And why don't you used the L and QSA flag? They are important.
Update2
Try this:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.tld
RewriteRule .* view.php?url=%1 [L,NC,QSA]
Use PHP only
$_SERVER['HTTP_HOST'] contains your full domain. This answer explains how to extract the subdomain name:
$subdomain = array_shift((explode('.', $_SERVER['HTTP_HOST'])));
Now you are able to use your general index.php to switch between your general page or the users subdomain content:
$domain_parts = explode('.', $_SERVER['HTTP_HOST']);
// access without any subdomain (TLDs like "co.uk" would "need == 4")
if (count(domain_parts) == 3) {
$subdomain = "www";
}
else {
$subdomain = array_shift($domain_parts);
}
if ($subdomain == 'www') {
// general page
}
else {
// users page
}

Is it possible to share informations between .htaccess and php?

Hi,
is it possible to share informations between a PHP-Script and .htaccess?
I was experimenting with $_ENV, but did not get it to work.
What I want to do:
Creating a login system. For every html-request, .htaccess is calling (via reWrite rule) a php and passing as parameter the original url.The PHP is testing if the user is logged in. If not: Go to the login page, if yes: Allow accessing the requested URL. That I did with php "header($url)".
The problem: This always starts a loop, because the PHP script is, after the logged-test is successfull, requesting the original url, which as again handled in the .htaccess by calling the PHP-Script.
My idea: Is there a way to set a variable in PHP, which I can access in .htaccess-condition? And is that a secure way?
Update:
As asked for, here my code.
PHP:
session_start();
$sOriginUrl = $_GET["url"];
if(!$sOriginUrl){
return false;
}
if($_SESSION["userName"]) {
if($_SESSION["userName"] !== null){
header("Location: " . $sOriginUrl, TRUE, 301);
}
else {
$aTokenizedOriginalUrl = explode("/", $sOriginUrl);
$sLoginUrl = "/";
for($i=0, $il=count($aTokenizedOriginalUrl); $i<($il-1); $i++) {
$sLoginUrl = $sLoginUrl . $aTokenizedOriginalUrl[$i] . "/";
}
header("Location: //myurl.de/" . $sLoginUrl);
}
}
else {
$aTokenizedOriginalUrl = explode("/", $sOriginUrl);
$sLoginUrl = "/";
for($i=0, $il=count($aTokenizedOriginalUrl); $i<($il-1); $i++) {
$sLoginUrl = $sLoginUrl . $aTokenizedOriginalUrl[$i] . "/";
}
$_ENV["HTTP_user_logged"]="true";
header("Location: //myurl.de/" . $sLoginUrl);
}
.htaccess:
RewriteEngine on
# This prevents the rewrite engine from looping
RewriteCond %{ENV:HTTP_user_logged} true
#RewriteCond %{forced_responsecode} 301
RewriteRule ^ - [L]
#RewriteCond %{ENV:REDIRECT_STATUS} !=""
RewriteCond %{HTTP_REFERER} !^/myurl.de/basics/validate-user-login-for-url.php$
RewriteCond %{REQUEST_URI} !^(/.*)/$
RewriteCond %{REQUEST_URI} !^(/.*)/index.html$
RewriteRule ^(.*\.html)$ /myurl.de/basics/validate-user-login-for-url.php?url=%{REQUEST_URI}&ref=%{HTTP_REFERER} [L,QSA]
Thanks for any help!!
I'm afraid what you are asking is not possible. PHP cannot share information with .htaccess because the latter is checked before PHP is executed, so the workflow is "req ->.htaccess -> php; req -> .htaccess -> php", but the only thing is preserved between requests is cookies, and no it's not secure to save the login state in the cookie, you need to use sessions, and PHP sessions are not available in .htaccess
So the solution I propose is that every file in your project which requires user to be authenticated includes a file "check_auth.php" at the beginning, then your check_auth.php can include() the login page and exit() if not logged in, or simply do nothing if the user is logged in (which means the originally invoked script continues its execution.
Hope this helps. Cheers

How to process Clean URLs and Queries?

I have decided to build a web application using clean urls. However its seems to be quite hard for at first. I have experienced many problems during testing and I couldn't figure out how is it recommended to build Clean URLs basically.
I have finally decided to redirect everything to the index.php and process the URI from there.
This is my .htaccess file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=$0 [QSA]
In the PHP end I have created this, so only the URLs in the array will be passed:
$root_path = '/';
$uri = $_SERVER['REQUEST_URI'];
$url = array(
$root_path . 'login' => 'login'
);
$url_basic = array_keys($url);
$url_slash = array_keys($url);
array_walk($url_slash, function(&$value, $key) { $value .= '/'; return $value;});
if (in_array($uri, $url_basic) || in_array($uri, $url_slash)) {
$uri = rtrim($uri,'/');
require $url[$uri] . '.php';
exit();
} else {
echo 'Bad';
}
So basically if someone types: /login or /login/ they'll have the login.php required, otherwise they'll stay on the index.php page (as APACHE redirects everything else).
Question:
Let's say that the user has received an error while trying to log in. In this case I guess the best way (or if its not the best way, please tell me) to pass a $_GET variable with the name of 'error' for example. So the user would get: /login/?error=1
How is it possible to achieve that result? Because if I type that I get redirected to the index.php page. Can anyone please help me?
You can look at $_SERVER['QUERY_STRING'] at cut the query string out of $_SERVER['REQUEST_URI']:
if ($_SERVER['QUERY_STRING'])
echo substr($_SERVER['REQUEST_URI'], 0, -strlen($_SERVER['QUERY_STRING']) - 1);
The -1 is there to remove the question mark as well.
But setting the error in GET is not necessary. You can use a flash message and store the error in the session. You can find a simple way to use them here.
Maybe you should consider using a routing system as that of
Symfony: http://symfony.com/doc/current/book/routing.html
or its slimmer counterpart
Silex: http://silex.sensiolabs.org/doc/usage.html#routing

Redirected to the Homepage when removed www. from URL

Say, My Website is : www.example.com
I have one page : www.example.com/contactus
If I remove "www." from above url, means : example.com/contactus
It redirects me to the homepage. Why ??
Checkout Following Image of .htaccess :
What is the Solution for it ??
Check your .htaccess file for something similar to the following:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://your.domain.com/ [R=301,L]
You can change the second line to:
RewriteRule ^(.*)$ http://your.domain.com/$1 [R=301,L]
And it will instead redirect to whatever page you requested without the 'www' and put the 'www' back in front.
If you don't find it, you may have a redirect set up in the Magento admin or some other configuration set in your httpd.conf or virtual hosts file.
Update
Try adding this to your .htaccess file and see if it fixes your issue (please test in a development environment first):
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
The issue seem to be that you are using the building magento feature 'Auto-redirect to Base URL' in Admin -> System -> Configuration -> Web
But this feature seem to be misleading, because it DOES NOT seem to append the url path (only redirect you to the base url http://www.site.com instead of http://www.site.com/path/to/xyz.html).
So the quick fix would be to use .htaccess rewrite.
Take a look baseUrl which is the url to be redirected to
$baseUrl = Mage::getBaseUrl(
Mage_Core_Model_Store::URL_TYPE_WEB,
Mage::app()->getStore()->isCurrentlySecure()
);
....
Mage::app()->getFrontController()->getResponse()
->setRedirect($baseUrl, $redirectCode)
->sendResponse();
See /app/code/core/Mage/Core/Controller/Varien/Front.php
/**
* Auto-redirect to base url (without SID) if the requested url doesn't match it.
* By default this feature is enabled in configuration.
*
* #param Zend_Controller_Request_Http $request
*/
protected function _checkBaseUrl($request)
{
if (!Mage::isInstalled() || $request->getPost()) {
return;
}
$redirectCode = (int)Mage::getStoreConfig('web/url/redirect_to_base');
if (!$redirectCode) {
return;
} elseif ($redirectCode != 301) {
$redirectCode = 302;
}
if ($this->_isAdminFrontNameMatched($request)) {
return;
}
$baseUrl = Mage::getBaseUrl(
Mage_Core_Model_Store::URL_TYPE_WEB,
Mage::app()->getStore()->isCurrentlySecure()
);
if (!$baseUrl) {
return;
}
$uri = #parse_url($baseUrl);
$requestUri = $request->getRequestUri() ? $request->getRequestUri() : '/';
if (isset($uri['scheme']) && $uri['scheme'] != $request->getScheme()
|| isset($uri['host']) && $uri['host'] != $request->getHttpHost()
|| isset($uri['path']) && strpos($requestUri, $uri['path']) === false
) {
Mage::app()->getFrontController()->getResponse()
->setRedirect($baseUrl, $redirectCode)
->sendResponse();
exit;
}
}
I suspect this is nothing to do with mod_rewrite, but Magento itself. Navigate to System->Configuration->Web in admin. Under URL Options you most likely have Auto-redirect to Base URL set to yes. Your base URL's under Secure and Unsecure are likely http(s)://www.example.com/ rather than http(s)://example.com/. When accessing the store via example.com it doesn't match the base URL so you get redirected to www.example.com.

auto redirect to clean urls

how can i auto redirect a site from dirty url to clean url in php , something like
http://www.mysite.com?page=page1&action=action1
to
http://www.mysite.com/page1/action1
You have to check if it was clean request or not.
Otherwise you will fall into infinite loop
Here is an example from one of my projects:
.htaccess
RewriteEngine On
RewriteRule ^game/([0-9]+)/ /game.php?newid=$1
game.php
if (isset($_GET['id'])) {
$row = dbgetrow("SELECT * FROM games WHERE id = %s",$_GET['id']);
if ($row) {
Header( "HTTP/1.1 301 Moved Permanently" );
Header( "Location: /game/".$row['id']."/".seo_title($row['name']));
} else {
Header( "HTTP/1.1 404 Not found" );
}
exit;
}
if (isset($_GET['newid'])) $_GET['id'] = $_GET['newid'];
So, you have to verify, if it was direct "dirty" call or rewritten one.
And then redirect only if former one.
You need some code to build clean url too.
And it is also very important to show 404 instead of redirect in case url is wrong.
If you are running Apache you can use the mod_rewrite module and set the rules in a .htaccess file in your httpdocs folders or web root. I don't see any reason to invoke a PHP process to do redirection when lower level components will do the job far better.
An example from Simon Carletti:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/page\.php$
RewriteCond %{QUERY_STRING} ^id=([0-9]*)$
RewriteRule ^(.*)$ http://mydomain.site/page/%1.pdf [R=302,L]
try
header("Location: http://www.mysite.com/".$_GET['page']."/".$_GET['action']);
you should check whether the values are set before trying to redirect

Categories