I've just moved all my server and web apps over from apache to nginx.
I have one app which created short urls, it did this by create a 6 letter file and inside the file is simply the URL. I've managed to recreate the nginx rewrite rule so that it locates the file and opens its as php (instead of just downloading it as there is no .php extension on the files) however the script sees it as an invalid hash (as seen in the code below) is there anyway to simply this now just get my current links working, they all just contain a URL at the top, I want it to ignore the check and redirect to the URL irregardless.
Here is the script which is loading
<?php
if($_GET['id']){
$id = addslashes($_GET['id']);
if(file_exists("urls/$id"))
{
$url = file_get_contents("urls/$id");
header("location:".$url);
} else {
echo "Error : invalid hash";
}
} else {
echo "Error : no hash";
}
?>
and it loads a file calling something like, for example "0ke0ea9ts" which will contain a url and nothing else.
I'm allowing the original links created (eg url.com/p/0ke0ea9ts) to work with the following Nginx redirect code (note they're installed in the sub-directory of /p/ hence the reference)
if (!-e $request_filename){
rewrite ^(.*)$ /p/show.php?id=$1 last;
so now as I said, it redirects opens them via the show.php but gives me the invalid hash message, how can I force it to just run the URL without the check?
Related
I want to prevent direct access to my error page which is 404.php but I want that this page can be accessed when redirected from the other page.
Like my website name is example.com/index.php and if any user mistyped in any way like example.com/ind.php it will be redirected to my 404.php to do that in my .htaccess file I have used.
Also, suppose in my index.php file I am showing some products when clicked on any product it is taking me to product.php?pid=4 where pid contains the id, now I have put a condition that if id!=4 or it does not exist then redirect it to 404.php.
Everything up to this working very fine but if I access example.com/404.php it is showing me the page, I just want that the user when will direct use example.com/404.php it will redirect to index.php file. That's it.
# enable url rewriting
RewriteEngine On
ErrorDocument 404 http://localhost/news_21_off/404.php
Index.php
$sql = "select * from products";
$res = mysqli_query($co,$sql);
$rs = mysqli_fetch_assoc($res);
$res_id = $rs['id'];
Product
Products.php
if(isset($_GET['pid']) && $_GET['pid']=='4'){
echo 'correct';
}else{
header('location:404.php');
}
404.php
<h1>My 404 page</h1>
So far I have found no way of doing it.
Everything up to this working very fine...
Actually, I don't think it is...
...prevent direct access to a php page but can be accessed when redirected
This isn't just any PHP page. It is your 404 "Not Found" error document.
You should not be externally 3xx redirecting to your error document in the first place. The error document should be served in the same request (an "internal subrequest"). This is the root cause of your problem.
The redirected request is an entirely separate request, mostly indistinguishable from a "direct request", which will naturally make reliably blocking direct requests "impossible". However, do you really need to block "direct requests" to your 404 error document? (See below...)
ErrorDocument 404 http://localhost/news_21_off/404.php
By specifying an absolute URL (ie. with a scheme + hostname) in the ErrorDocument directive, Apache will trigger a 302 external redirect to the stated URL. The user sees a 302 response (not a 404), followed by a 200 "OK" (not a 404) from the redirected request, unless you manually send the 404 "Not Found" status in your PHP code (there is no evidence of that here).
Just because Apache allows you to "redirect" to the error document, doesn't mean you should. As noted in the Apache docs:
Note that when you specify an ErrorDocument that points to a remote URL (ie. anything with a method such as http in front of it), Apache HTTP Server will send a redirect to the client to tell it where to find the document, even if the document ends up being on the same server. This has several implications, the most important being that the client will not receive the original error status code, but instead will receive a redirect status code. This in turn can confuse web robots and other clients which try to determine if a URL is valid using the status code.
In addition, all the helpful PHP superglobals (passed from Apache) that ordinarily relate to the URL that triggered the 404 are lost (eg. $_SERVER['REDIRECT_STATUS'], $_SERVER['REDIRECT_URL'], etc.) because, as mentioned above, the redirected request is an entirely separate request.
99.99% of the time you should be using a root-relative URL-path in the ErrorDocument directive, so that Apache triggers an internal subrequest for the error document, for example:
ErrorDocument 404 /news_21_off/404.php
header('location:404.php');
Likewise, you should not be "redirecting" to your error document in your PHP code either.
In PHP, there are various ways to resolve this. You could simply include() the error document at the point in your code you wish to serve the 404.
For example, in your products.php script:
<?php
$pid = $_GET['pid'] ?? null;
if ($pid == '4') {
echo 'correct';
} else {
// 404 Not Found
include($_SERVER['DOCUMENT_ROOT'].'/news_21_off/404.php');
exit();
}
However, the above won't send a 404 HTTP status code to the client. In your PHP 404 error document you should set the HTTP status to ensure that a 404 status is sent by PHP and when/if the document is accessed directly by the user.
For example, in your 404.php script:
<?php
http_response_code(404);
?>
<h1>My 404 page</h1>
Incidentally, setting the HTTP status code in your PHP script will override any status that Apache might have set when serving an error document.
Now, back to your initial question...
I want to prevent direct access to my error page which is 404.php
Why?
Having implemented the changes above, if a user does "directly access" your 404 error document they are simply served a 404 and see the same response as if they had requested any other document that didn't exist.
So, unless you have a specific requirement, there is nothing more you need to do here.
I have a domain which I want every attempted url after https://www.example.com/someFolder/ to not give an error but instead give a php page.
For example, I do not have a somefolder/abc.php file but going there will run a process.php file instead and display it there.
I have attempted to modify the 404 page as the process.php but that also modifies the example.com/ error page which I do not want.
It would be great if I do not need to modify/add a file at the root directory
PS. adding a .htaccess to the somefolder folder does work somewhat but then the url shows somefolder/404.php and not somefolder/abc.php
Modify your 404 page as you did putting php script there but check in php if the url that was requested was directory or not. Depending on that make an appropriate action
<?php
$url = $_SERVER[REQUEST_URI];
// check if requested url was ending with slash
$pattern = '#\/$#';
$result = preg_match($pattern, $url);
if ($result === 1) {
//request was to directory suffixed with slash
//do your php code for custom 404
die; //end the page generation
}
?>
request was not to directory ending with slash
put html of regular 404 page here or leave it blank
I have learned that I could turn somefolder into somefolder.php and use the $_SERVER['PATH_INFO'] to make all pages exist.
This is something that can only be done, in the general case, by using the .htaccess file, and redirecting every request like this...
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,NC,L]
After that, you can use $_SERVER, $_SESSION, and other global variables in index.php to decide how to handle a 404 error (i.e., you can implement here how to define what a 404 is, etc.).
For instance, $_SERVER['PATH_INFO'] will be able to tell you what URL was requested, and you can use a combination of file_exists() and other calls, to determine if you want to display a full 404, search results, a redirect, or simply to display the results of another script.
This works for example.com/somefolder/, example.com/some/other/folder/, and example.com/a/b/c/d/e/f/g/, etc..
I have a dilemma here...
At the moment I'm launing a website and there are a lot of old url that needs to be redirected to it's new url without .stm extension. And the new site is running Durpal.
Ex.
http://www.foo.com/foo/bar.stm --> http://www.foo.com/foo/bar
So I went looking more into nginx.conf setting to rewrite the url before it even hit setting.php that is being used by drupal. Turns out that my host doesn't let me touch the conf file on the root folder. but my only solution is add this to the conf file in root
server { location / { rewrite ^(.*)\.stm$ $1 permanent; } }
At this point, I'm running out of options but to redirect every pages in Drupal manually ( that is roughly about 650 pages )
I've also tried every other modules, but non offers extension strip redirect.
My other option is using 404 landing page to run php and redirect any url with .stm and redirect with scrubbed url without .stm and stays in 404 if it's not a .stm url.
This is my best bet, URL rewriting with PHP
But it's over complicated just for a extension strip and redirect?
You should be able to check if the requested URI contains ".stm", and if so then redirect to the exact same URI with the ".stm" ripped. Put something like this in your settings.php:
if (strrpos(request_uri(), '.stm') !== FALSE) {
header("Location: " . str_replace('.stm', '', request_uri()));
exit;
}
How do I get the value of an URL eg. www.example.php/folders/crowd? I'm trying to echo out crowd with PHP. I have tried using the $_SERVER ['SCRIPTNAME'] but I really cant get it to work.
To get the current directory of the file (which is just "crowd" in your "www.example.php/folders/crowd" example), use:
$cur_dir = basename(dirname($_SERVER[PHP_SELF]))
If you just want the file, then try this:
$cur_file = $_SERVER[PHP_SELF];
You can use parse_url, because scriptname will return the real php file execution "index.php" for example.
php > var_dump(parse_url('http://www.example.php/folders/crowd', PHP_URL_PATH));
// "/folders/crowd"
But if you want just the last part you can:
$tmp = explode('/', 'www.example.php/folders/crowd');
var_dump(end($tmp));
// "crowd"
Or another way:
var_dump(basename(parse_url('http://www.example.php/folders/crowd', PHP_URL_PATH)));
// "crowd"
Maybe you want to have a look at the Apache module mod_rewrite. Many web hosting provider offer this module. If you even operate a dedicated server owned by you, it's no problem to install / enable this module.
mod_rewrite can be used to transparently "transform" request URLs to requests for defined php scripts with query string parameters derived from the original request. This is often used for SEO-friendly URLs like http://mywebpage/article/how-to-cook-pizza-123.html. In this case a script might be invoked taking only the 123 from the URL as a parameter (e.g. http://mywebpage/article/how-to-cook-pizza-123.html => /article.php?id=123).
In your case you could use a configuration like this (put this into an .htaccess file or your Apache/vhost configuration):
RewriteEngine on
RewriteRule ^folders/[A-Za-z]+$ showfolder.php?user=$1 [L]
Your showfolder.php might look like this:
<?php
if (isset($_GET['user'])) {
echo htmlentities($_GET['user']);
} else {
echo "No parameter found.";
}
?>
Any word after folders/ that consists of letters (A-Z and a-z) will be taken as the user parameter of your php script. Then you can easily echo this value, fetch it from a database or whatever. For example, a request for /folders/crowd will result in your script being executed with this parameter: showfolder.php?user=crowd. The user of your website won't see anything of this hidden internal forwarding.
If you use some other web server software (nginx, ...): There are similar modules for other web server products, too.
I want to rearrange my web site, and move all customer pages into a directory (/customerPages), while keeping the same URL (URL to access the page and the URL that is showed in the browser). I'm using Apache and PHP (CakePHP).
I've tried rewiring my 404 error page in the following way:
// Redirect customers to customers landing pages under /customerPages
if (strpos($message,'customerPages') == false) {
$url = 'http://'.$_SERVER['HTTP_HOST'].'/customerPages'.$message;
$homepage = file_get_contents($url);
echo $homepage;
}
But this solution breaks all images written using relative paths.
Later I've tried using redirection instead:
if (strpos($message,'customerPages') == false) {
$url = 'http://'.$_SERVER['HTTP_HOST'].'/customerPages'.$message;
header("Location: ".$url);
}
But than the URL changes. I've tries fiddling with RewriteRule with no luck.
How can I achieve this using the first,second or any other method?
Another way, just basic idea:
1. Put in your /oldpath/.htaccess file (we handle file not found 404 error):
ErrorDocument 404 /oldpath/redirect.php
2. /oldpath/redirect.php file (our handler) - make redirect to new path only if file exists in newer location:
$url = parse_url($_SERVER['REQUEST_URI']);
$filename = basename($url['path']);
if(file_exists('/newpath/'.$filename)) {
header('Location: /newpath/'.$filename);
}else{
header('Location: /your_real_404_handler');
}
You need to redirect image requests from newer location (/customerPages) to the old path.
You can use mod_rewrite apache module to redirect such requests back:
RewriteEngine on
RewriteRule ^/customerPages/(.*\.jpg|.*\.gif|.*\.png) /oldpath/$1 [R]