PHP Apache mod_rewrite - php

Here's the basic information:
I'm using WAMP on Windows 8 64 bit. Apache 2.4.2, PHP 5.4+.
My project files are located in http://localhost/test/.
The .htaccess file in this folder is:
RewriteEngine on
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
If I enter a URL like http://localhost/test/some/cool/stuff/, it works fine
i.e. in PHP: $_SERVER['QUERY_STRING'] = index.php&some/cool/stuff/
I wish it stripped the index.php& as well but I'm doing that in PHP.
While if I enter a URL like http://localhost/test/some/cool/stuff
the PHP $_SERVER['QUERY_STRING'] returns index.php&some/cool/stuff/&some/cool/stuff
Where's this &some/cool/stuff/ part coming from?

I use RewriteRule ^(.+)$ index.php [L]
And then get the URL by $_SERVER['REQUEST_URI']
I use this function for PHP to get the request URL with fallback.
private static function get_request_URL() {
if (isset($_SERVER["REDIRECT_URL"])) {
$realURL = $_SERVER["REDIRECT_URL"];
} elseif (isset($_SERVER["REQUEST_URI"])) {
list($realURL) = explode("?", $_SERVER["REQUEST_URI"]);
} else {
return null;
}
$realURL = rtrim(trim(strtolower($realURL)), "/");
if ($realURL == "") {
$realURL = "/";
}
return $realURL;
}

Related

Rewrite URL string for username in root directory Apache

Currently I have the following .htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}% !-d
RewriteCond %{REQUEST_FILENAME}% !-f
RewriteRule \.(js|css)$ - [L]
RewriteRule ^/?u/(.*?)/?$ /user-profile?user_id=$1 [L]
RewriteRule ^(.+)$ index.php [QSA,L]
It rewrites all files and directories to index.php, which does further routing, ignoring static js/css files.
With this line:
RewriteRule ^/?u/(.*?)/?$ /user-profile?user_id=$1 [L]
I am redirecting all requests to something like website.com/user-profile?user_id=timm to website.com/u/timm. I'm trying to figure out how to make it redirect to simply website.com/timm, but everything I have tried so far has given me a 500 error.
Here is the solution I ended up going with, if anyone ever finds themselves in a similar situation. It might not match up to anyone else's use case, but you never know.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}% !-d
RewriteCond %{REQUEST_FILENAME}% !-f
RewriteRule \.(js|css)$ - [L]
RewriteRule ^/?edit-list/(.*?)/?$ /edit-list?list_id=$1 [L]
RewriteRule ^(.*)$ index.php?username-router=$1 [QSA,L]
My entire router looks like this:
// Routing
$redirect = $_SERVER['REDIRECT_URL'];
$method = $_SERVER['REQUEST_METHOD'];
// Get the path after the hostname
$path = ltrim($redirect, '/');
// Check if path matches a user
$username = $userControl->getUserByUsername(ltrim($path));
// Get controller name by converting URL of dashes
// (such as forgot-password) to uppercase class names
// (such as ForgotPassword) and assign to the proper
// controller based on URL.
$controllerName = getControllerName($redirect);
$controllerPath = $root . "/src/controllers/{$controllerName}.php";
// Load index page first
if ($controllerName === '') {
$controller = new Index($session, $userControl);
}
// If the controller exists, route to the proper controlller
elseif (file_exists($controllerPath)) { // to do: add approved filenames
$controller = new $controllerName($session, $userControl);
}
// If path matches user in the database, route to the public
// user profile.
elseif ($username) {
$controller = new UserProfile($session, $userControl);
}
// If all else fails, 404.
else {
$controller = new ExceptionNotFound($session, $userControl);
}
// Detect if method is GET or POST and route accordingly.
if ($method === 'POST') {
$controller->post();
} else {
$controller->get();
}

PHP - Get IP when page calling by htaccess

I have a website in PHP and need to know what the IP of the accessing client is. For this I am using the function below:
function get_client_ip() {
$ipaddress = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ipaddress = $_SERVER['REMOTE_ADDR'];
}
return $ipaddress;
}
But when accessing the site by url omenorpreco.com/teste the page returns the server IP.
When access to page the url omenorpreco.com/teste.php, the page returns the client IP.
Possibly this error occurs because when you access the page without the extension ".php", the server interprets the page by .htaccess?
How can I adjust my application for both accesses, return the client's IP, and not the server IP?
above my htaccess code
php_value allow_url_fopen on
php_value allow_url_include 1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !.(js|ico|txt|gif|bmp|jpeg|jpg|png|css|log|rss|zip|xml|sql|pdf|doc|docx|xls)$ url_amigavel.php
RewriteRule sitemap-categoria.xml$ sitemap.php?number=categoria
RewriteRule sitemap-([0-9]+).xml$ sitemap.php?number=$1
RewriteRule sitemap_index.xml$ sitemap_index.php
and url_amigavel.php code
<?php
$geturl = explode( "/", str_replace( strrchr( $_SERVER["REQUEST_URI"], "?" ), "", $_SERVER["REQUEST_URI"] ) );
array_shift( $geturl );
$tipo = $geturl[0];
if ( is_file( "$tipo.php" ) )
{
include "$tipo.php";
}
else
{
echo "page not found";
}
?>
EDIT: CAN I SET GLOBAL_VAR IN HTACCESS WITH THE CLIENT IP?
I think I just saw it work on your server!
Change .htaccess to;
php_value allow_url_fopen on
php_value allow_url_include 1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !.(js|ico|txt|gif|bmp|jpeg|jpg|png|css|log|rss|zip|xml|sql|pdf|doc|docx|xls)$ url_amigavel.php
RewriteRule sitemap-categoria.xml$ sitemap.php?number=categoria
RewriteRule sitemap-([0-9]+).xml$ sitemap.php?number=$1
RewriteRule sitemap_index.xml$ sitemap_index.php
SetEnvIfNoCase Remote_Host "(.*)" HTTP_MY_REMOTE_HOST=$1
SetEnvIfNoCase Remote_Addr "(.*)" HTTP_MY_REMOTE_ADDR=$1
An change test.php to;
function get_client_ip() {
if (isset($_SERVER[REDIRECT_HTTP_MY_REMOTE_ADDR])) {
return $_SERVER[REDIRECT_HTTP_MY_REMOTE_ADDR];
} else if (isset($_SERVER[REDIRECT_HTTP_MY_REMOTE_HOST])) {
return $_SERVER[REDIRECT_HTTP_MY_REMOTE_HOST];
} else if (isset($_SERVER[HTTP_MY_REMOTE_ADDR])) {
return $_SERVER[HTTP_MY_REMOTE_ADDR];
} else if (isset($_SERVER[HTTP_MY_REMOTE_HOST])) {
return $_SERVER[HTTP_MY_REMOTE_HOST];
}
}
echo get_client_ip();
Inspiration for setting variables in .htaccess from: http://www.askapache.com/htaccess/setenvif.html
Glad it finally worked!
Put this in a file and run with and without the extension:
<?php
function get_ip_address() {
return $_SERVER['REMOTE_ADDR'];
}
echo get_ip_address();
?>
What error do you get if you run the above?
EDIT:
Can you edit your .htaccess like this and see if the error still occurs:
php_value allow_url_fopen on
php_value allow_url_include 1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !.(js|ico|txt|gif|bmp|jpeg|jpg|png|css|log|rss|zip|xml|sql|pdf|doc|docx|xls)$ $1.php [L]
RewriteRule sitemap-categoria.xml$ sitemap.php?number=categoria
RewriteRule sitemap-([0-9]+).xml$ sitemap.php?number=$1
RewriteRule sitemap_index.xml$ sitemap_index.php
You have allow_url_include set to 1 on your .htaccess. This is causing problems because as you are telling PHP to include a file, the preprocessor thinks it's a URL, other people have told you this so let's go straight.
My guess is, just disable allow_url_include. It's a bad practice, a security risk and there's nothing you can't do just with file_get_contents for example.
If you are still convinced that including remote files is a good idea, you should try using a full path, using this include with the code Benjy1996 gave you:
include(getcwd().$tipo.".php");
PD: you should probably change your ip function to return $_SERVER['REMOTE_ADDR'] only as well, as it's the one you can trust the most, because it's the most difficult to fake.

Htaccess rewrite rules for this url

I just started to learn htaccess and i'd like to rewrite my current urls from this:
http://www.url.com/?location=script
To:
http://www.url.com/script
So far i've managed to do this but now i want to have a directory with more controllers so i can have something like this:
http://www.url.com/script/method
Structure: Script directory --> method.php
Currently my directory structure for includes its like this:
assets-->client(directory):
login.php
logout.php
register.php
something.php
And i'd like to access these using a url like:
url.com/client/login
url.com/client/logout
url.com/client/register
url.com/client/something
My .htaccess:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?location=$1 [L]
</ifModule>
PHP based inclusion code:
####################################################################
# PARSE THE CURRENT PAGE #
####################################################################
$includeDir =".".DIRECTORY_SEPARATOR."assets/controllers".DIRECTORY_SEPARATOR;
$includeDefault = $includeDir."home.php";
if(isset($_GET['ajaxpage']) && !empty($_GET['ajaxpage'])){
$_GET['ajaxpage'] = str_replace("\0", '', $_GET['ajaxpage']);
$includeFile = basename(realpath($includeDir.$_GET['ajaxpage'].".php"));
$includePath = $includeDir.$includeFile;
if(!empty($includeFile) && file_exists($includePath)) {
include($includePath);
}
else{
include($includeDefault);
}
exit();
}
if(isset($_GET['location']) && !empty($_GET['location']))
{
$_GET['location'] = str_replace("\0", '', $_GET['location']);
$includeFile = basename(realpath($includeDir.$_GET['location'].".php"));
$includePath = $includeDir.$includeFile;
if(!empty($includeFile) && file_exists($includePath))
{
include($includePath);
}
else
{
include($includeDefault);
}
}
else
{
include($includeDefault);
}
All my controllers are in assets/controllers/ucp/login.php for example.
How about:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^(/client/[a-zA-Z0-9_\-]+)$
RewriteRule ^[a-z]+ index.php?location=$2 [L]
</ifModule>
It does include a leading slash and doesn't have the PHP extension. But this can be altered in PHP to suit your needs.
Be wary though, your code gives access to all your PHP files. You might want to check $_GET['location'] against an array of allowed locations. Consider the following URL as example of how this could go wrong
http://example.com/index.php?location=../drop_database.php

Get params not being passed

I have an API based application written in slim. I have been testing on my local computer and things have been working OK.
I pushed to the server and I noticed that i cant retrieve the parameters passed via a get request
While debugging, i observed the following
Post requests are working fine
An attempt to use $_GET['param'] fails as i get an undefined index error.
To get a parameter value in slim, i write
$app->request()->get('param');
URL request : {api}/hospital/get_locations?hospital_id=1
var_dump($_GET): array(1) { ["/hospital/get_locations"]=> string(0) "" }
Any pointers as to why this might be happening?
Content of .htaccess file
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
EDIT
There might be a way of getting get request params using the $_SERVER['REQUEST_URI']. I did a quick test on my localhost and came up with the following. Try it out, might work for you.
php
<?php
// Function
function getParams() {
$params = array();
$urlParts = parse_url($_SERVER['REQUEST_URI']);
if (isset($urlParts['query'])) {
$query = $urlParts['query'];
if (-1 !== strpos($query, '&')) {
$query = explode('&', $query);
} else {
$query = array($query);
}
foreach ($query as $queryStr) {
list($key, $val) = explode('=', $queryStr);
$params[$key] = $val;
}
}
return $params;
}
// Usage
$params = getParams();
// Debug
echo "<pre>";
print_r($params);
echo "</pre>";
?>
output
Array
(
[hospital_id] => 1
)
.htaccess (similar to yours)
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
</IfModule>

Rewrite Url Parameters - Change http://myweb/?dept=dept&app=app to http://myweb/dept/app

I've currently got a web application that I need optimizing, and one of methods or something I'm trying to achieve is such:
http://myweb/dept/app
from
http://myweb/?dept=dept&app=app
I've currently this as the PHP code for it:
if(empty($_REQUEST['dept'])) {
$folder = "apps/";
} else {
$folder = str_replace("/", "", $_REQUEST['dept']) . "/"; }
if(empty($_REQUEST['n'])) {
include('user/home.php');
} else {
$app = $_REQUEST['n'];
if(file_exists($folder.$app.".php")) {
include($folder.$app.".php");
} else {
include("global/error/404.php");
}
}
How do I do this?
I'm currently half there with:
RewriteRule ^([A-Za-z]+)$ /index.php?app=$1
but that only rewrites part of it.
Thanks
The way many frameworks do this is with one of the following rules:
RewriteRule ^(.*)$ /index.php?q=$1
RewriteRule ^(.*)$ /index.php
In the 1st case you get the query string in $_GET["q"].
In the 2nd case you have to get the query string from $_REQUEST or something. (just do some var_dumps till you find what you need).
Then you explode("/") this and you're all set.
Have a look at how TYPO3, eZPublish, Drupal do this.
You should also add the following conditions to allow the site to open your static files (like images/css/js/etc). They tell apache to not do the rewrite if the URL points to a location that actually matches a file, directoy or symlink. (You must do this before the RewriteRule directive)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
This should work:
RewriteRule ^([A-Za-z]+)/([A-Za-z]+)$ index.php?dept=$1&app=$2 [QSA]
You need the QSA part in order for any GET parameters to be appended to the rewritten URL.
You might find that it can be more flexible to rewrite everything to index.php, and then handle splitting up the url there, e.g.
.htaccess:
#only rewrite paths that don't exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
PHP:
<?php
$parts = explode('/', $_SERVER['PATH_INFO']);
$dept = isset($parts[0]) ? $parts[0] : 'someDefault';
$app = isset($parts[1]) ? $parts[1] : 'anotherDefault';

Categories