Selecting for special characters with rewriterule in htaccess file - .htaccess

I made a little mistake (I started a new php call within an existing php call - oops) and managed to have google start crawling a whole bunch of urls that look like this:
http://www.mydomain.com/folder/parameter/%3C/?php%20echo%20writelink();%20?%3E
I've fixed the sourcing call, but my attempts to have .htaccess rewite the page calls to
http://www.mydomain.com/folder/parameter/
have been unsuccessful.
I have tried the following:
RewriteRule ^folder/(.*)/(.*)%(.*) /folder/$1/ [NE,R=301,L]
RewriteRule ^folder/(.*)/(.*)3C/?php /folder/$1/ [R=301,L]
RewriteRule ^folder/(.*)/(.*)writelink /folder/$1/ [R=301,L]
RewriteRule ^folder/(.*)/([^/.]+)writelink /folder/$1/ [R=301,L]
But all of them are returning the same 403.
I have the test rewriterule as the first rewriterule in the file, so it isnt being usurped by something else.
(For reference, the correct rewriterule when I havent mucked up the page is
RewriteRule ^folder/(.*)/$ /content/element.php?param=$1 [L]
)
I've had problems with %ages in the path before but this time I've decided to defeat it - any suggestions?

Your URL is something like this:
http://www.mydomain.com/folder/parameter/</?php echo writelink(); ?> whithout the encoding.
The 304 code does not really indicate an error, it indicates the resource for the requested URL has not changed since last accessed or cached. Clear your brower's cache and make sure it is cleared.
The error should be 403 (Forbidden) because of the initial character < (%3C).
These errors make any rewrite rule at .htaccess useless. One way to handle this kind of problem is with a script.
EXAMPLE
Add these lines to your .htaccess file at root directory:
Options +FollowSymlinks -MultiViews
ErrorDocument 403 /Error403.php
Create Error403.php at root directory with a content similar to this one:
<?php
// The following lines should be at the top of the file
/**************Only for Debugging**********************/
echo $_SERVER[ 'REDIRECT_QUERY_STRING' ] . "<br /><br />";
echo var_dump($_REQUEST) . "<br /><br />";
/*=====================================================
NOTE: A Header error might be generated while the above
code is active. Use it only to display the incoming
parameters and delete it for normal operation.
*******************************************************/
if ( isset ( $_SERVER[ 'REDIRECT_QUERY_STRING' ] ) ) {
$QueryString = $_SERVER[ 'REDIRECT_QUERY_STRING' ]; // The query looks like this: php%20echo%20writelink();%20?%3E
// Check if it is the wrong URL
if ( preg_match( '|php%20echo%20writelink()|i', $QueryString ) ) {
header("Location: http://www.mydomain.com/folder/parameter/");
}
}
// Handle other errors
?>
In this specific case we take advantage of the fact that the string contains a question mark ?, that makes it look like a query. So we try to match the query content with preg_match().
That should do it. Modify the links accordingly if necessary, this is just an example on how to do it.

Related

how do i display the user nickname instead of the ID on the page profile [duplicate]

Normally, the practice or very old way of displaying some profile page is like this:
www.domain.com/profile.php?u=12345
where u=12345 is the user id.
In recent years, I found some website with very nice urls like:
www.domain.com/profile/12345
How do I do this in PHP?
Just as a wild guess, is it something to do with the .htaccess file? Can you give me more tips or some sample code on how to write the .htaccess file?
According to this article, you want a mod_rewrite (placed in an .htaccess file) rule that looks something like this:
RewriteEngine on
RewriteRule ^/news/([0-9]+)\.html /news.php?news_id=$1
And this maps requests from
/news.php?news_id=63
to
/news/63.html
Another possibility is doing it with forcetype, which forces anything down a particular path to use php to eval the content. So, in your .htaccess file, put the following:
<Files news>
ForceType application/x-httpd-php
</Files>
And then the index.php can take action based on the $_SERVER['PATH_INFO'] variable:
<?php
echo $_SERVER['PATH_INFO'];
// outputs '/63.html'
?>
I recently used the following in an application that is working well for my needs.
.htaccess
<IfModule mod_rewrite.c>
# enable rewrite engine
RewriteEngine On
# if requested url does not exist pass it as path info to index.php
RewriteRule ^$ index.php?/ [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?/$1 [QSA,L]
</IfModule>
index.php
foreach (explode ("/", $_SERVER['REQUEST_URI']) as $part)
{
// Figure out what you want to do with the URL parts.
}
I try to explain this problem step by step in following example.
0) Question
I try to ask you like this :
i want to open page like facebook profile www.facebook.com/kaila.piyush
it get id from url and parse it to profile.php file and return featch data from database and show user to his profile
normally when we develope any website its link look like
www.website.com/profile.php?id=username
example.com/weblog/index.php?y=2000&m=11&d=23&id=5678
now we update with new style not rewrite we use www.website.com/username or example.com/weblog/2000/11/23/5678 as permalink
http://example.com/profile/userid (get a profile by the ID)
http://example.com/profile/username (get a profile by the username)
http://example.com/myprofile (get the profile of the currently logged-in user)
1) .htaccess
Create a .htaccess file in the root folder or update the existing one :
Options +FollowSymLinks
# Turn on the RewriteEngine
RewriteEngine On
# Rules
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php
What does that do ?
If the request is for a real directory or file (one that exists on the server), index.php isn't served, else every url is redirected to index.php.
2) index.php
Now, we want to know what action to trigger, so we need to read the URL :
In index.php :
// index.php
// This is necessary when index.php is not in the root folder, but in some subfolder...
// We compare $requestURL and $scriptName to remove the inappropriate values
$requestURI = explode(‘/’, $_SERVER[‘REQUEST_URI’]);
$scriptName = explode(‘/’,$_SERVER[‘SCRIPT_NAME’]);
for ($i= 0; $i < sizeof($scriptName); $i++)
{
if ($requestURI[$i] == $scriptName[$i])
{
unset($requestURI[$i]);
}
}
$command = array_values($requestURI);
With the url http://example.com/profile/19837, $command would contain :
$command = array(
[0] => 'profile',
[1] => 19837,
[2] => ,
)
Now, we have to dispatch the URLs. We add this in the index.php :
// index.php
require_once("profile.php"); // We need this file
switch($command[0])
{
case ‘profile’ :
// We run the profile function from the profile.php file.
profile($command([1]);
break;
case ‘myprofile’ :
// We run the myProfile function from the profile.php file.
myProfile();
break;
default:
// Wrong page ! You could also redirect to your custom 404 page.
echo "404 Error : wrong page.";
break;
}
2) profile.php
Now in the profile.php file, we should have something like this :
// profile.php
function profile($chars)
{
// We check if $chars is an Integer (ie. an ID) or a String (ie. a potential username)
if (is_int($chars)) {
$id = $chars;
// Do the SQL to get the $user from his ID
// ........
} else {
$username = mysqli_real_escape_string($char);
// Do the SQL to get the $user from his username
// ...........
}
// Render your view with the $user variable
// .........
}
function myProfile()
{
// Get the currently logged-in user ID from the session :
$id = ....
// Run the above function :
profile($id);
}
Simple way to do this. Try this code. Put code in your htaccess file:
Options +FollowSymLinks
RewriteEngine on
RewriteRule profile/(.*)/ profile.php?u=$1
RewriteRule profile/(.*) profile.php?u=$1
It will create this type pretty URL:
http://www.domain.com/profile/12345/
For more htaccess Pretty URL:http://www.webconfs.com/url-rewriting-tool.php
It's actually not PHP, it's apache using mod_rewrite. What happens is the person requests the link, www.example.com/profile/12345 and then apache chops it up using a rewrite rule making it look like this, www.example.com/profile.php?u=12345, to the server. You can find more here: Rewrite Guide
ModRewrite is not the only answer. You could also use Options +MultiViews in .htaccess and then check $_SERVER REQUEST_URI to find everything that is in URL.
There are lots of different ways to do this. One way is to use the RewriteRule techniques mentioned earlier to mask query string values.
One of the ways I really like is if you use the front controller pattern, you can also use urls like http://yoursite.com/index.php/path/to/your/page/here and parse the value of $_SERVER['REQUEST_URI'].
You can easily extract the /path/to/your/page/here bit with the following bit of code:
$route = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
From there, you can parse it however you please, but for pete's sake make sure you sanitise it ;)
It looks like you are talking about a RESTful webservice.
http://en.wikipedia.org/wiki/Representational_State_Transfer
The .htaccess file does rewrite all URIs to point to one controller, but that is more detailed then you want to get at this point. You may want to look at Recess
It's a RESTful framework all in PHP

Revising my ReWrite Code

Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*)\.html$ fetch.php?id=$1
I have this in my htaccess file and it works fine, but I want to know if there is a way to rewrite this so that instead of just pulling the id # i can pull the category and title up instead or will i need to do something like this
RewriteRule (.*)/(.*)/(.*)\.html$ fetch.php?id=$1&category=$2&title=$3
Also if this is what I need to do, how will I go about changing my title to have no spaces and only have dashes inbetween them? I heard that urls don't like spaces. I have read somewhere else they used a php code where the spaces were turned into "-" or "_" to be read into the page but reverted back to be read in sql. Let me know if you need to know more about my situation. Thanks.
UPDATE!
RewriteRule (.*)/(.*)/(.*)\.html$ fetch.php?id=$1&category=$2&title=$3
This is the htaccess rule
<a href="<?php echo $row_getDisplay['id']; ?>/<?php echo $row_getDisplay['category']; ?>/<?php echo urlencode($row_getDisplay['title']); ?>">
that is my link .. this method I get it to pull up with id/category/title with no spaces but it has no css or images displaying. i'm pulling by ID because that's how my fetch.php is pulling it i don't know how to set it so it pulls by category and title.
this method I get it to pull up with id/category/title with no spaces but it has no css or images displaying. i'm pulling by ID because that's how my fetch.php is pulling it i don't know how to set it so it pulls by category and title.
This is probably because all your links are relative, and the base URI has changed from /something.html (i.e. /) to /something/foo/bar.html (i.e. /something/foo/) so all the relative links are now broken. Try adding this to the header of your pages:
<base href="/">
I would advise against doing this as this is not very extensible, you might want to try the following:
Add the following in your htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* fetch.php/%{REQUEST_URI} [QSA,L]
This will put your entire url into the path_info environment variable, which you can than use in your backend code.
The RewriteCond parts make sure the url only gets rewritten if the file requested doen't actually exist.

htaccess - creating directories and files of the same name

I want to create a bunch of files without an extension showing at the end. The easiest way to do that was to do this:
/usa/index.php
/usa/alaska/index.php
/usa/alabama/index.php
/usa/california/index.php
What I want to do is this
/usa/alaska.php
/usa/alabama.php
/usa/california.php
and have it show up as:
/usa/alaska
/usa/alabama
/usa/california
However, I have one more level I want to add to this, the cities
/usa/alaska/adak.php
/usa/alaska/anchorage.php
/usa/california/los-angles.php
I don't want the ".php" showing up, but then each state exists as both a file and a directory. What I want is an htaccess rule that serves up the file version of the file, not the directory which is the default. I also want to strip the .php off of the end of the files so the final result looks like
/usa
/usa/alaska (alaska.php)
/usa/alaska/adak (adak.php)
I know I can get close to this by creating all the directories and using index.php for each directory, but then I will have thousands of directories each with one file in it and updating is a pain in the butt. I would much rather have one directory with 1000 files in it, than 1000 directories with 1 file in it.
Please, can someone point me in the right direction and know that I am doing this for all 50 states.
Jim
I would also suggest using a single php (e.g. index.php) file and redirecting all urls starting with usa to it, instead of separating them in different directories and files. The you'd need a couple of rewrite rules like the following
RewriteEngine On
RewriteRule ^usa/([^/.]+)$ index.php?state=$1 [L]
RewriteRule ^usa/([^/]+)/([^/.]+)$ index.php?state=$1&city=$2 [L]
So then in your index.php you'd only need to check the $_GET parameters.
Update:
If you don't feel comfortable enough to use a database and pull the needed data from there you could always use the parameters to dynamically include/require the needed files. Something like this
<?php
$source = ''; //or the 'ROOT' directory
if(isset($_GET['state'])) $source .= $_GET['state'].'/';
if(isset($_GET['city'])) $source .= $_GET['city'].'.php';
include($source); // here $source would be something like 'alaska/adak.php'
// and is assumed that the dir 'alaska' is on the same
// level as 'index.php'
?>
But to answer your original question nevertheless you could use the following .htaccess
RewriteEngine On
RewriteRule ^usa/([^/.]+)$ usa/$1.php [L]
RewriteRule ^usa/([^/]+)/([^/.]+)$ usa/$1/$2.php [L]
what about creating just one single file:
/usa/index.php
With
$_SERVER["REQUEST_URI"]
you can read the current URI.
Well, now if a user enters "http://domain.foo/usa/alaska" for example, he will get an 404 error of course.
But to call your index.php instead, you could write this line to the .htaccess:
ErrorDocument 404 /usa/index.php
Now the index.php receives everything what is written to the URI and you can match the result and include files or handle errors.
But maybe there is a better solution with .htaccess only, don't know. :)

Save HTTP_REFERER with mod_rewrite?

actually I'm trying to pass referers inside the .htaccess. What I'm trying to do is that the referer value shall be send to a PHP script where this value will be saved to a databse. In some cases (depending on the referer) the image shall be blocked (hot linking) and in some other cases the image shall be shown normally. But it will not work :-( My current "try" looks like the following (it is just for testing, so currently every image will be handled):
RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified} ^$
RewriteRule (.*)jpg$ /include/referrer.php?ref=%{REQUEST_FILENAME}&uri=%{REQUEST_URI}&query=%{QUERY_STRING}&env=%{ENV:verified} [E=verified:yes]
RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified} ^yes$
RewriteRule ^(.*)$ %{REQUEST_FILENAME} [E=verified:no]
The referrer.php look like:
<?
log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
?>
The problem is that the referrer.php is called but the image will not be displayed, which is obvious because the second rule is not reached.
I also have tried to display the image inside of the referrer.php, like:
<?
log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
$src = str_replace($_SERVER['DOCUMENT_ROOT'],'',$_REQUEST['ref']);
?>
<img src="<? echo $src ?>" />
But then the .htaccess is called again and I will run into endless loops.
The question is now: how can I access the second rule or how can I achieve what I want to do. Is there any way to do that?
Thanks for your help,
Lars
Your current solution doesn't work because mod_rewrite can only be used to rewrite the request to a single destination, but you seem to want the request to take a detour to your PHP script, then continue onward to the image. It might be possible to cause a subrequest that would cause the PHP script to get triggered, but I don't think it would be possible to control whether or not the original request continued on to the image in that scenario.
The best course of action here is to have your PHP file print out the actual image data (not an image tag referencing the image) after it does whatever checking/logging you intend it to do. You can do this with readfile(), provided that you send the right headers. After making sure the file is one of the images you want to serve up (and not some arbitrary file on your system...), you'll at least need to determine the appropriate content type, then print out the data. It's also a good idea to take caching (see this answer, as well as this one) into consideration.
Combining some of the techniques mentioned, a simple pseudo-example of the referrer script would be as follows. Note that you should research the best way to implement the techniques described, and you need to pay particular attention to security since you're opening files and printing their contents.
$filename = /* sanitized file name */;
log_img(/* log some data about the request */);
if (file_exists($filename) && allowedToView($filename)) {
// Assume we're not on PHP 5.3...
$types = array(
'gif' => 'image/gif',
'png' => 'image/png',
'jpg' => 'image/jpg',
);
$parts = pathinfo($filename);
$ext = strtolower($parts['extension']);
if (array_key_exists($ext, $types)) {
$mime = $types[$ext];
$size = filesize($filename);
$expires = 60 * 60 * 24 * 30;
if (!empty($_SERVER['IF-MODIFIED-SINCE'])) {
$modified = filemtime($filename);
$cached = strtotime($_SERVER['IF-MODIFIED-SINCE']);
if ($modified <= $cached) {
header('HTTP/1.1 304 Not Modified');
exit();
}
}
header("Content-Type: $mime");
header("Content-Length: $size");
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires)
. ' GMT');
header('Cache-control: private, max-age=' . $expires);
readfile($filename);
exit();
}
}
header("HTTP/1.0 404 Not Found");
exit();
And as far as the .htaccess file goes, it would just be something like this (the stuff that you added to the query string is available in $_SERVER anyway, so I see no point in manually passing it to the script):
RewriteEngine on
RewriteRule \.(jpg|png|gif)$ /include/referrer.php [NC]

How to insert an "index.php" into every url using .htaccess?

Example: My Site gets called like that:
www.mysite.com/controller/method/parameter1/parameter2
Now, .htaccess needs to rewrite this URL into:
www.mysite.com/index.php/controller/method/parameter1/parameter2
But the problem is: In case of an img, css or js directory, no redirection should happen.
How can I achieve this? What must I put to .htaccess? I just added this line but nothing happens:
RewriteCond $1 !^(css|js|images)
I haven't tested it, but this should work:
RewriteRule !^((css|js|images)/.*)$ index.php%{REQUEST_URI} [L, NE]
%{REQUEST_URI} will be the original /controller/method... stuff, including the ?query part hopefully. NE prevents double escaping of stuff, and L means no further rules are applied.

Resources